【问题标题】:Implementing one dimensional gsl integration in C++ with parameters as border of integration在C++中实现一维gsl集成,参数作为集成边界
【发布时间】:2020-09-08 00:37:06
【问题描述】:

我想在 C++ 中使用 gsl 执行以下一维积分,

I(x) = int_{x/4}^1 dy y^{3/2+a} (1-y)^{1/2} exp(1.13*sqrt(log(4y/x))), 其中ax 被视为积分的常数,我希望能够对x 在区间0.000001<x<0.001 中采样为固定的a 执行积分由用户。

这是我的尝试:

 #include <iostream>
 #include <iomanip>
 #include <fstream>
 #include <vector>
 #include <string>
 #include <cmath>
 #include <gsl/gsl_integration.h>
 #include <stdio.h>
 #include <math.h>

double integrand(double y, void * params) {
double a = *(double *) params;
double x = *(double *) params; 

double intg = pow(y,3e0/2e0+a)*pow(1-y,1e0/2e0)*exp(1.13*sqrt(log(4*y/x)));

return intg;

}

double integral(double a) {

gsl_integration_workspace * w
= gsl_integration_workspace_alloc (1000);
gsl_function F;
F.function = &integrand;                 
F.params = &a;
double result, error;

for(int i = 0; i<100; i++) {
    double x = (0.001-0.000001)*i/100 + 0.000001;


gsl_integration_qags (&F, x/4, 1e0, 0, 1e-7, 1000,
                      w, &result, &error);

}
 gsl_integration_workspace_free (w); // Free memory

return result;
}




int main(){
std::cout << "x" << x << "result "<< integral(-0.046)<<std::endl;

 }

我遇到的问题是如何将 for 循环给出的x 的值传递给被积函数?目前,代码返回nan,因为我没有将x 传递给被积函数,只是传递给下集成边界中的x 依赖项。仍然是 C++ 的新手,所以提前为我的问题的简单性道歉。

【问题讨论】:

    标签: c++ gsl numerical-integration


    【解决方案1】:

    如果积分下限(“x/4”表达式)中表示的x与参与被积函数公式的x相同,则解如下:

    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <vector>
    #include <string>
    #include <cmath>
    #include <gsl/gsl_integration.h>
    #include <stdio.h>
    #include <math.h>
    
    //create a structure for the parameters of the integral function: 
    
    struct params 
    {
        double a;
        double x;
    };
    
    //create an integration function for the x variable: 
    //let all INTERNAL parameters have a prefix "_" in the name:   
    
    double integrand(double y, void * params_from_above)
    {
        //declare our structure for parameters and be sure to do type casting, 
        //and initialize the parameter values passed from above:
        params& _inner_params = *(params*)params_from_above;
        
        //we calculate the value of the integrand using the passed parameter values:
        double _intg = pow(y, 1.5 + _inner_params.a) * pow(1.0 - y, 0.5) * exp(1.13 * sqrt(log(4.0 * y/_inner_params.x)));
    
        return _intg;
    }
    
    
    double integral(double a)
    {
        double result, error;
        
        //declare a structure for storing and passing "a" and "x" parameters:
        params custom_params;
        //create integration workspace:
        gsl_integration_workspace * w = gsl_integration_workspace_alloc (1000);
        
        //declare and initialize gsl callback function for integrand:
        gsl_function F;
        F.function = &integrand;
        
        //declare and initialize gsl params structure:
        //(so far only for the value of "a" parameter)
        F.params = &custom_params;    
        custom_params.a = a;
    
        //start the main cycle of calculations:    
        for(int i = 0; i < 100; i++)
        {
            //compute x parameter value:
            double _x = (0.001-0.000001)*i/100 + 0.000001;
            //save the value of the X parameter for sending to the integrand:
            custom_params.x = _x;
            
            //compute the integral for current "x"/4 parameter value:
            gsl_integration_qags (&F, _x/4.0, 1.0, 0, 1e-7, 1000, w, &result, &error);
            
            //output integral value:
            printf("res = %f\n", result);
            //delay: press any key for continue: 
            system("pause");
    
        }
        gsl_integration_workspace_free (w); // Free memory
    
        return result;
    }
    
    int main()
    {
        //here you are mistaken, since only the last value is displayed...
        //but I left your expression for the sake of calling an integral function:
        std::cout << "result "<< integral(-0.046) << std::endl; 
    } 
    

    对于前五个“x”参数值,我得到以下输出:

    C:\Users\...\CLionProjects\gsl_test\cmake-build-debug\gsl_test.exe
    res = 15.226887
    Press any key to continue . . .
    
    res = 10.523077
    Press any key to continue . . .
    
    res = 9.467232
    Press any key to continue . . .
    
    res = 8.870463
    Press any key to continue . . .
    
    res = 8.459477
    Press any key to continue . . .
    

    【讨论】:

    • 非常感谢,就这样。你能解释一下代码 sn -p 'params& _inner_params = (params)params_from_above;' 是什么意思吗?我知道进行了一些转换,因为内部变量是指向 void 类型的指针,而 params 成员是 double 类型?但我想一点一点地理解这个sn-p。非常感谢。
    • params&amp; _inner_params = *(params*)params_from_above;左侧:这意味着我们在 params 类型上创建引用(对结构类型的引用)。右边:我们显式地转换类型:将void* 类型转换为params*(指针类型到指针类型!)然后我们从指针中获取值!这是一个很简单的表达式,从右到左读取:取void指针,转换为params指针,然后从这个指针中取值,并用这个值初始化引用。
    • 谢谢。所以要检查我的理解:params_from_abovevoid 类型的指针,所以*(params*)params_from_aboveparams_from_above 转换为params 类型的指针。然后内部变量_inner_params 通过&amp; 使用该指针指向的VALUE 进行初始化。这是正确的意思吗?
    • 是的,几乎是对的,但更简单:) _inner_params -- 它只是一个reference,即别名,pseudonym庞大的结构*(params*)params_from_above。使用 *(params*)params_from_above 代替引用,因为引用 -- 更简单、更短且更安全。再一次 - 我们将 _inner_params 声明为结构类型变量并立即通过从指针中获取 VALUE 进行初始化(我们使用最左边的 * 将 VALUE 获取到 *(params*)params_from_above 表达式中)。 P.S.:如果我的代码版本对您有帮助,请将其标记为解决方案:)
    • 非常感谢,这确实更有意义。 +1 并接受
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 1970-01-01
    • 2018-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多