# Compute 2D numerical double integration with Boost C++ with parameters

I am trying to compute the double Richardson and Wolf integrals for the focusing of a lens with Boost in C++ (using the Gauss Kronrod method).

As a starting point, I used the example presented in this question. My problem is that I have to perform several integrations (looping in the image space) with variable parameters depending mainly on the position of the point in the image plane and eventually on the optical properties of the pupil.

In order to easily update the parameters at each iteration (I did'nt want to pass by global variables) and to make simpler the writing of the integrand, I used an Integrand class where some public member functions correspond to the functions to be integrated and the private properties to the parameters to be updated.

#ifndef INTEGRAND_H
#define INTEGRAND_H
#include <cmath>
#include <complex>

using complex = std::complex<double>;

class integrand
{
public:
integrand();
void set_k(double k);
void set_rp(double rp);
void set_thetap(double thetap);
void set_phip(double phip);
complex ex(double theta,double phi);
complex ey(double theta,double phi);
complex ez(double theta,double phi);
private:
double _k;
double _rp;
double _thetap;
double _phip;

};

#endif // INTEGRAND_H


as an example here is how I implemented the member function that allows to calculate the component of the electric field along the x axis:

complex integrand::ex(double theta,double phi){
complex cos_e = (cos(theta)*cos(_thetap)+sin(theta)*sin(_thetap)*cos(phi-_phip),0);
complex part1 = (sqrt(cos(theta))*sin(theta)*(cos(theta)+1-cos(theta)*sin(phi)*sin(phi)),0);
complex part2 = (cos(_k*_rp*cos_e),sin(_k*_rp.*cos_e));
double pupil = 1;
return part1*part2*pupil;
}


I call this member function in my calculation loop (in my main) after having updated the parameters and following the method presented in the question mentioned above:

///compute I0
auto f0 = [](double theta){
auto g0 = [&](double phi){
return I.ex(theta, phi);
};
return gauss_kronrod<complex,61>::integrate(g0,0,2*M_PI, 5);
};
complex I0 = gauss_kronrod<double,61>::integrate(f0,0,a, 5, 1e-9, &error);


There, during compilation, I got a I is not captured error followed by the lambda has no capture default and Integrand I declared here (pointing on the line where I instanciate I). I understand that the way I defined or called the integrand::ex function is problematic, but I don't see how to fix the problem.

What is wrong with this approach? Should I proceed completely differently?

• Did you try to write auto f0 = [&](double theta) instead of auto f0 = [](double theta)? @BertrandSimon
– VoB
Aug 19 at 12:56
• Yes, it seems to be the good way... Indeed, I don't really understand the meaning of the & without referencing to a specific variable. So, I tried auto f0 = [&I](double theta) and there is no more compilation errors. Now I am finishing to rewrite my code in order to test if I can obtain the expected result. Aug 19 at 13:47
– VoB
Aug 19 at 14:36

The compiler is telling you that he's not able to capture I. This is just a C++ issue. You can just have a look at what a lambda expression is. Basically, it's just a shorthand for a functor.

As an example, consider the following:

double phi = 2.0;
auto capture_by_value = [] (double x) {return x + phi;};
std::cout << capture_by_value(2.0)<<"\n";


The error message will be essentially identical to the one you got before. Also, it's self-explanatory: you need to capture the variable phi

//Better yet: capture phi by reference:
auto capture_by_reference = [&phi] (double x)->double {return x + phi;};
std::cout << capture_by_reference(2.0)<<"\n";


Notice that by capturing by references you are allowed to modify the values you captured. This is not the case if you capture by copy, i.e. simply writing [phi].