Memisahkan beberapa fungsi C++ variabel untuk integrasi kuadratur

Saya ingin mengintegrasikan secara numerik dengan boost::math::quadrature::trapezoidal(g, a, b, 1e-6); Di sini saya mengintegrasikan fungsi g(x). Masalahnya adalah saya harus melakukan integral ganda. Selain itu, saya memiliki 4 variabel dalam fungsi yang ingin saya integrasikan. 2 di antaranya saya lewati saat mengintegrasikan (m,n) dan 2 lainnya adalah variabel integrasi (r,z). Ini adalah integral yang ingin saya hitung:

$$ \int_0^b\int_0^af(r,z)\sin{(\frac{n\pi}{a}z)}J_0(\frac{\alpha_{ 0,m}}{b}r)dzdr $$

Saya melihat contoh ini Melakukan integrasi numerik 2d dengan Boost Cpp dan memperhatikan bahwa dia menggunakan fungsi lambda untuk membagi integran utama menjadi 2. sejauh ini saya telah berhasil

double integrate(int m, int n)
{ 
  auto f1 = [](double r, double z, int m, int n) { return integrand(r,z,m,n); };
  auto f = [&](double r, m) {
         auto g = [&](double z, n) {
            return f1(r, z);
              };
         //return gauss_kronrod<double, 61>::integrate(g, 0, a, 5);
         return boost::math::quadrature::trapezoidal(g, 0, a, 1e-6);
       };
  double error;
  //double Q = gauss_kronrod<double, 15>::integrate(f, 0, b, 5, 1e-9, &error);
  double Q =  boost::math::quadrature::trapezoidal(f, 0, b, 1e-6);
  //std::cout << Q << ", error estimated at " << error <<std::endl;
  return Q;
}

Implementasi fungsi $f(r,z)$ dan integral lainnya adalah sebagai berikut

double initial(double r, double z, int m, int n)
{
return std::sin(M_PI*n*z/a)*std::cyl_bessel_j(0, boost::math::cyl_bessel_j_zero(0,m)*r/b);
}
double integrand(double r,double z,int n,int m)
{
  return initial(r,z,m,n)*std::sin(M_PI*n*z/a)*std::cyl_bessel_j(0, boost::math::cyl_bessel_j_zero(0,m)*r/b);
}

Biasanya Inisial tidak memerlukannya dan n variabel tetapi dalam kasus ini, saya perlu melakukan beberapa tes.

Masalahnya adalah saya benar-benar tidak mengerti cara membagi fungsi saya seperti pada contoh masalah saya dan melakukan integrasi karena boost hanya menerima 1 fungsi variabel.

Tolong bantu


person Carlos Andrés del Valle    schedule 29.04.2021    source sumber
comment
Untuk melihat apa yang terjadi, buat fungsi terpisah untuk semua lambda. Selain itu, Anda kehilangan m dan n saat mengembalikan f1 dari fungsi lambda g.   -  person Biswajit Banerjee    schedule 29.04.2021
comment
Hai, soalnya boost hanya menerima 1 fungsi variabel, jadi g dan f harus 1 varialbe saja, tidak tahu harus berbuat apa dengan m dan n.   -  person    schedule 29.04.2021
comment
Ini terlihat seperti pertanyaan pemrograman tentang cara meneruskan parameter ke lambda, jadi sepertinya di luar topik di sini.   -  person Federico Poloni    schedule 29.04.2021
comment
@CarlosAndrésdelValle: Anda tidak perlu memanggil fungsi boost dengan dua argumen. Kalikan saja argumennya dengan m atau n sebelum Anda mengirimkannya untuk meningkatkan.   -  person Biswajit Banerjee    schedule 29.04.2021


Jawaban (1)


Ide dasarnya adalah, seperti biasa, untuk mengintegrasikan dalam dua langkah. Untuk melakukan hal ini, pertama-tama Anda perlu menyelesaikan integral dalam dan membuat fungsi satu dimensi lain dari integral tersebut, yang kemudian diteruskan lagi ke integrator.

Lambda digunakan kapan pun Anda ingin mengurangi fungsi multi-parameter menjadi fungsi parameter tunggal. Dalam hal ini, Anda memasukkan semua yang bukan variabel terintegrasi ke dalam tangkapan lambda.

Berikut ini pseudocodenya:

double integrand(double r,double z, int m,int n, double a, double b)
{
   //this is the function you want to integrate
}

double integrate(int m, int n)
{
    double a=1.0;
    double b=1.0;

    auto inner_integral = [m,n,a,b](double z)
    {
        auto f = [z,m,n,a,b](double r) { return integrand(r,z,m,n,a,b);} 
        return trapezoidal(f,0,a);
    }
    return trapezoidal(inner_integral,0,b);
};

Anda mungkin tidak perlu menulis tangkapan lambda, yaitu tangkapan referensi dengan & kemungkinan akan berfungsi juga (auto inner_integral = [&](double z){...}).

person davidhigh    schedule 29.04.2021
comment
Terima kasih atas jawaban anda. Saya punya pertanyaan, kompiler berteriak tentang missing ; atau , sebelum pengembalian terakhir, dan mengatakan bahwa fungsi tersebut tidak memiliki pernyataan pengembalian. Bagaimana saya bisa mengatasinya? Apa itu ; di } terakhir? - person ; 29.04.2021
comment
Ya, dan itu benar. Setelah braket lambda terakhir, sebelum kembali, harus berupa ;. - person davidhigh; 30.04.2021