Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

C/++/# How to integrate when one of the limits is a variable?

  1. Jun 13, 2017 #1
    I'm trying to integrate a simple function (x*y) using the Romberg method.
    Question 1:
    I want to integrate only x and maintain the argument y present in the rest of calculation, like a global variable. In fortran 77 I would use common.
    Question 2:
    How to integrate using arguments in the limits. For example:
    f(x,y)=x*y
    intervals-y->[x,1]
    intervals-y->[0,1]

    PS: Integration using values in the limits are okay.

    Routine obtained from https://people.sc.fsu.edu/~jburkardt/cpp_src/nintlib/nintlib.html


    double f1(int dim_num,double x[]){
    double *a;
    double *b;
    int dim;
    int eval_num;
    int ind;
    int it_max = 3;
    double result;
    int *sub_num;
    double tol;
    //
    // Set the integration limits.
    //

    a = new double[dim_num];
    b = new double[dim_num];
    sub_num = new int[dim_num];

    a[0]=0.0; <- x[0] or x[1]?
    b[0]=1.0;
    tol = 0.0001;
    for ( dim = 0; dim < dim_num; dim++ )
    {
    sub_num[dim] = 20;
    }
    result = romberg_nd ( f0, a, b, dim_num, sub_num, it_max, tol,
    &ind, &eval_num );

    delete [] a;
    delete [] b;
    delete [] sub_num;
    // cout << result << endl;
    return result;
    }

    double f0(int dim_num,double x[]){
    double value;
    value=x[0]*x[1];
    return value;
    }
     
  2. jcsd
  3. Jun 14, 2017 #2

    Mark44

    Staff: Mentor

    I don't see how you can do this. Your function isn't really that "simple" as it involves two variables. Romberg is a numerical method for integration -- you seem to be wanting to to symbolic integration. For example, it's easy enough to find approximate values for the derivative of f(x) = sin(x) at a variety of points, but it's a completely different problem to have a program tell you that the derivative of sin(x) is cos(x).

    Having global variables or a common block is not a solution. In all of the numerical methods, numbers go in, numbers, not symbols, come out.

    Is there a typo here? You have intervals-y twice. In any case, the routine you're using wants the function to be one with just one variable, not two.
     
  4. Jun 14, 2017 #3
  5. Jun 25, 2017 #4

    ChrisVer

    User Avatar
    Gold Member

    What stops you from using a grid of f(x,y)?
     
  6. Jun 25, 2017 #5

    Mark44

    Staff: Mentor

    He was interested in using Romberg integration, which works for functions of a single variable.
     
  7. Jun 25, 2017 #6
    I was looking on the the internet about this method of integration, but it is unclear to me how to apply it through a simple example.
    I have already solved my problem using the change of variable.
    Do you have a simple example in fortran, python or c++ for I study it?

    Now, I'm still trying to find how pass a variable (common in fortran) in c++. I guess that is possible to do this using struct or static, but my attempts had no effects. For example, in this code, I used the numerical recipes with Romberg integration.
    I'm newbie in C++, that is why I have some basic doubts on how to pass variables between functions.

    #include <iostream>
    #include <iomanip>
    #include <cmath>
    #include "nr.h"
    #include <cstdlib>
    using namespace std;

    DP func0(const double x)
    {
    return x*y; <- y variable to be integrated after integration in x
    }


    DP func1(const double y1){
    r=NR::qromb(func0,0.0,3.0);
    return r;
    }


    int main(void)
    { double s;
    s=NR::qromb(func1,0.0,1.0);
    cout << "Result from routine QROMB is " << setw(12) << s << endl;
    return 0;
    }
     
    Last edited: Jun 25, 2017
  8. Jun 25, 2017 #7

    ChrisVer

    User Avatar
    Gold Member

    Ehmm you can't have an undefined variable in a function (if it's not global)... in func0 you will get an error... That's why I initially asked if you could make a chart of f(x,y) (like a table)...
    I don't know this method of integration though and it's tough for me to look into it now (on mobile). Also I don't know what qcomb/DP/NP are :( ... For passing functions as arguments in C++ you may look at pointer returning functions...
     
  9. Jun 25, 2017 #8
    You are right about the declaration of global variable. As I told before, in fortran 77 I use common/v/y inside the func0 and func1 and the both integrations are done properly. And in python we could use args=(y) that is used to pass the arguments.
     
    Last edited: Jun 25, 2017
  10. Jun 25, 2017 #9
    result = qromb(func, a, b) -> rotine to integration where a is the inferior limit and b the superior.
    DP -> is double in the numerical recipes library.
    Could you show me a simple example of the use of pointers for this case?
     
  11. Jun 26, 2017 #10

    Mark44

    Staff: Mentor

    Writing a function that has parameters in C or C++ isn't difficult, but this is something you need to work on. Using global variables or common blocks is really not the best way to go. If you do a web search for "C++ function parameters" there should be lots of hits with examples.
    This isn't going to work since y isn't declared anywhere. If a function needs two inputs (x and y), they should be passed as parameters.

    Also, what do you mean y is "to be integrated after integration in x"?
    Similar problem here as r isn't declared, and, as well, y1 is declared but not used. What is the purpose of having y1 if you don't use it?
    The line where s gets a value doesn't make sense to me. In this assignment you call the library function gromb(), passing func1 as a parameter. In your code for func1(), you call gromb.

    It would be helpful if you gave us the exact, verbatim problem description.
     
  12. Jun 26, 2017 #11

    Mark44

    Staff: Mentor

    I don't think this would be productive. If you don't understand basic parameter passing in functions, you definitely won't understand parameters passed as addresses.
     
  13. Jun 26, 2017 #12
    When I compile this code(for a function with only one variable x), it's works properly. Mark44, you are looking for the "mistakes" on my code example and you are not giving me a clear answer, even it seems ugly to a professional programmer like you, i'm newbie. If the ugly way works, the next step is to learn the details of language.

    #include <iostream>
    #include <iomanip>
    #include <cmath>
    #include "nr.h"
    #include <cstdlib>
    using namespace std;


    DP func(const double y){
    double r;
    r=pow(y,2);
    return r;
    }

    int main(void)
    { double s;
    s=NR::qromb(func,0.0,1.0);
    cout << "Result from routine QROMB is " << setw(12) << s << endl;
    return 0;
    }

    The code in the previous post was only to ilustrate my problem. I'm will never post a code without the proper variable declaration. As I'm using a routine for integration, even if it is a ugly way to pass a variable, I think that is more practical to do this than change the routine for each function to be integrated.
     
  14. Jun 26, 2017 #13
    Mark44, this is a forum. If you don't know, it is used to make question and get answers. If you don't want to answer the questions, ok. Or if it is more agreeable to you, imagine that all humans are stupids (except you) and you are the next Alan Turin to save the world.
    And as a see in a previous post here in the forum, that you sometimes used the argument of authority to make your point. It does not seem to me a good behavior of a university teacher or a retired teacher.
    I'm so sorry to offend your intelligence with my stupid questions.
     
    Last edited: Jun 26, 2017
  15. Jun 26, 2017 #14

    Mark44

    Staff: Mentor

    Your code here looks fine. I don't see any problems with it.
     
  16. Jun 26, 2017 #15

    Mark44

    Staff: Mentor

    When people ask well-defined questions, it's possible to provide meaningful answers. On the other hand, people sometimes ask questions that aren't at all clear, and it can take several additional questions from the people responding to get to the heart of the question.

    In post #6, you said this:
    If it's not clear to you how the parameter passing mechanism works in C or C++, then that's something you need to look into. I suggested a search string you could use to find more information. If you have a specific question, we're happy to answer it, but you shouldn't expect this forum to provide all the details and examples on parameter passing, a topic that can fill a full chapter (or more) in a C++ programming textbook.
    You are being overly sensitive. I don't think you are stupid, and nothing I wrote implies this. However, by your own admission, you don't have much knowledge in C++. The solution to this lack of knowledge is to expend some time on research, either on the web as I suggested earlier or by looking in a book on C++.
    Which post of mine are you referring to?
     
    Last edited: Jun 26, 2017
  17. Jun 26, 2017 #16

    ChrisVer

    User Avatar
    Gold Member

    OK, let me make a clear statement. Try answering the following:

    Q1: What is it you are trying to do? Are you trying to integrate: [itex]f(x,y)=xy[/itex]? What's the integral like? Is it:
    [itex]\int_0^1 dx \int_0^x dy~f(x,y)[/itex]
    ?

    Q2: What's your ("complete") code? Where does it fail (what errors do you get)? What do you want to do? In fact I don't understand the "I'm still trying to find how pass a variable (common in fortran) in c++" either. A variable is passed as a variable in C++.

    Q3: Have you tried solving an "easier" integration to make sure the functions of the libraries you are using work properly with your own code? Like one that doesn't have [itex]x[/itex] on the integral limits.
     
  18. Jun 26, 2017 #17
    Chris, now I found the right solution and what is the meaning of a grid in your answer. By the way, the 3 questions I have already solved. The question 1 I solved using the trick https://en.wikipedia.org/wiki/Integration_by_substitution like in example 1, but for a different parameterization. Here is my simple code (slow convergence) tested for 1D and 2D integration. The way to pass the variable between the functions is ugly, but it's works. :D
    Thanks for your readiness to help me.

    #include<iostream>
    #include<cmath>
    using namespace std;
    // to compile this code, use g++ -O3 filename.cpp
    // https://en.wikipedia.org/wiki/Trapezoidal_rule - trapezoidal method of integration in 1 dimension (slow method)
    // http://mathinsight.org/double_integral_examples - function used in this example

    static double yy;
    double trap(double f(double x), double a, double b, double n);
    double f1(double x);
    double f2(double y);



    int main(){
    double res,exactsol,error;
    res=trap( f2, 0.0,1.0, 1.E4);
    exactsol=2.0/3.0;
    cout << " The numeracally result is " << res << endl;
    cout << " The exact result is " << exactsol << endl;
    cout << " The error is " << res - exactsol << endl;

    return 0;

    }


    double trap(double f(double x), double a, double b, double n0){
    double sum, h,sol,err0,err;
    sum=0.0;
    h=(b-a)/(2.0*n0);
    for(double x1=a; x1<=b; x1+=h){
    sum+=f(x1);
    }
    sol=h*(sum+ f(a));

    err0=0.0;
    for(double n=1.0;n<=(n0-1.0);n+=1.0){
    err0+=f(a+((n*(b-a))/n0));
    }
    err=sol - ((b-a)/n0)*( (f(a)+f(b))/2.0 + err0 );
    // cout<<"the error in the integration is"<< err << endl; to reduce it, increase the n0.
    return sol;

    }

    double f2(double y){
    double res;
    yy=y;
    res=trap( f1, 0.0, 2.0, 1.E4);
    return res;
    }

    double f1(double x){
    double res;
    res=x*pow(yy,2);
    return res;
    }
     
    Last edited: Jun 26, 2017
  19. Jun 26, 2017 #18
    By the way, I was disregarding one big thing. The routines of integration were in different files(the definition in .cpp and the declaration in .hpp), so in this way, the approach that I was using would never work indeed. I've tried this simple case rekcha (7) (for constants) from this site [http://www.cplusplus.com/forum/general/21368/ ]
    and it works. But when I considered an argument inside a function it does not work. And in all routines bentioned before, the arguments were passed as an array. That is different from my trapezoidal routine that argument is explicit and allowed me to use static to turn yy visible at next integration.
    My argument is right, Chris?
     
  20. Jun 26, 2017 #19

    Mark44

    Staff: Mentor

    Fabio, please use code tags when you post code. These tags preserve your indentation, which helps make your code a lot more readable.
    They look like this:
    [code=c]
    int main()
    {
    int size = 5
    int count = 10;
    // etc.
    return 0;
    }[/code]

    I have added them to your code below.
     
  21. Jun 26, 2017 #20
    Perfect, Mark44. Thanks!
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: How to integrate when one of the limits is a variable?
Loading...