1

I need to solve ODE equations set with odeint library. "main.cpp" file is only to call calculation (it will be extended later, here simple version to keep code clean)

main.cpp

#include "calc.h"

int main()
{
    calc c;
    c.startC();
    return 0;
}

Here is the calc header, starC(); is set public. calc.h

#ifndef MAIN_H
#define MAIN_H

#include <iostream>
#include <boost/numeric/odeint.hpp>
#include <math.h>

using namespace std;
using namespace boost::numeric::odeint;

typedef std::vector< double > vector_type;

class calc
{
public:
    int main();
    void startC();
private:
    void solveODE(const vector_type &y , vector_type &ODE , const double t );
    void printR();

};

#endif // MAIN_H

Here is the main calculation part. Also here the error occurs: calc.cpp

include <iostream>

#include <boost/numeric/odeint.hpp>
#include <math.h>

#include "calc.h"

using namespace std;
using namespace boost::numeric::odeint;

const double g = 0.15;


void calc::solveO( const vector_type &y , vector_type &ODE , const double t )
{
    dy[0] =  y[1];
    dy[1] = -y[0] - g*y[1];
}

void calc::printR(const vector_type &y, const double t)
{
    cout << t << endl;
    cout << y[0] << endl;
}

void calc::startC()
{
    const double dt = 0.1;
    typedef runge_kutta_dopri5<vector_type> stepper_type;
    vector_type y(2);
    //Initial conditins
    y[0]=   1.0;
    y[1]=   0.0;


    //Initializing of ODE solver
    integrate_const(make_dense_output<stepper_type>( 1E-12, 1E-6 ), 
                    this->*solveO, y, 0.0, 1.0, dt , printResults); //ERROR HERE
}

int calc::main()
{
    return 0;
}

This operation ends with error on the level of "Initializing of ODE solver" with:

'((calc*)this)->calc::solveO' cannot be used as a member pointer,
since it is of type '<unresolved overloaded function type>'

What's wrong with this call:

this->*solveO

And what's the correct way to call solveO inside "integrate_const"?

Edit: Thanks to the help of @tobi303 and @rbelli it now works. Here I post sum-up, TL:DR explanation:

The easiest solution is to make solveO and printR free function and call:

integrate_const(make_dense_output<stepper_type>( 1E-12, 1E-6 ), solveO, y, 0.0, 1.0, dt , printR);
Karls
  • 731
  • 7
  • 17
  • Instead of this->*solve (as explained bellow by tobi303) you can use boost::bind(this, &calc::solveO, _1, _2, _3), or you can use a lambda function like [this](const vector_type &y , vector_type &ODE , const double t){this->solveO(y, ODE, t);} as the integrate_const accept functors. – rbelli Aug 30 '17 at 15:14

1 Answers1

1

If integrate_const takes a function pointer you cannot pass a member function pointer. Member function pointers are different from function pointers, because they implicitly need this as argument.

As you dont use any members of the class inside solveO you can simply make it a free function:

void solveO( const vector_type &y , vector_type &ODE , const double t )
{
    dy[0] =  y[1];
    dy[1] = -y[0] - g*y[1];
}
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • It explains a bit, but still doesn't point the correct call. I'm not very experienced in c++. I tried solutions suggested by @rbelli: 1.boost::bind fails: `"'bind' is not a member of 'boost'"` 2. Seems to interferes with integrate_const: `"must use '.*' or '->*' to call pointer-to-member function"` – Karls Aug 30 '17 at 16:10
  • @Karls hope this wont sound rude: experienced or not, you need to rtfm. I tried to look up what parameters `integreate_const` takes, but it is heavily templated, so I would also have to read their manual to know what can be passed. If you are lucky you can pass a functor or lambda. In any case I would stay away from `bind`, but thats just my personal preference – 463035818_is_not_an_ai Aug 30 '17 at 16:16
  • it's not about wrong parameters, so you hurried a little wit rtfm. I know how to execute integreate_const. Look here (last answer): https://stackoverflow.com/questions/26747492/comparison-of-odeints-runge-kutta4-with-matlabs-ode45 If I code all one file like in this example, it works. The problems start when I use a class as I presented in OP. And for some reasons I need it in this form, as it will be part of bigger program. Do you understand now where is the real problem? – Karls Aug 30 '17 at 16:28
  • @Karls if it is not about parameters then what is it about? You definitely cannot pass a member function pointer without also passing an instance. I dont know what parameters you can pass to `integrate_const`, otherwise I could tell you how to solve it. Btw dont try to be javaish. Not everything has to be in a class, just because classes are cool.... – 463035818_is_not_an_ai Aug 30 '17 at 16:32
  • @Karls ...Anyhow there is no good reason why the function you pass must be a member function. You dont even use any members of the class. – 463035818_is_not_an_ai Aug 30 '17 at 16:33
  • I tried to use it as free function (basing on your edited answer). And it still fails somwhere: call: `integrate_const(make_dense_output( 1E-12, 1E-6 ), solveO, y, 0.0, 1.0, dt , printR)` ends again with `must use '.*' or '->*' to call pointer-to-member function` – Karls Aug 30 '17 at 17:05
  • @Karls `printR` is a member function, and the same is true for that aswell: No reason to make it member of a class, it uses parameters passed to it and nothing else – 463035818_is_not_an_ai Aug 30 '17 at 17:14
  • @Karls there is no advantage of a function being a member function as opposed to being a free function. In fact the lesser member function a class has the better it is. You can be happy for every function that does not need to be member of a class, because it makes your code simpler – 463035818_is_not_an_ai Aug 30 '17 at 17:17