octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Avoid global pointers in dae


From: Francesco Faccio
Subject: Re: Avoid global pointers in dae
Date: Mon, 15 Aug 2016 10:42:43 +0000


Carlo de Falco<address@hidden> wrote:
> On 15 Aug 2016, at 09:09, Francesco Faccio <address@hidden> wrote:
>
> >
> > Carlo de Falco<address@hidden> wrote:
> > >On 14 Aug 2016, at 02:11, Carlo de Falco <address@hidden> wrote:
> > >
> > >>
> > >> On 14 Aug 2016, at 01:17, Carnë Draug <address@hidden> wrote:
> > >>
> > >>> On 13 August 2016 at 06:30, Francesco Faccio
> > >>> <address@hidden> wrote:
> > >>>> [...]
> > >>>> Since I don't own copiright, I would like to know if it's ok to change the
> > >>>> interface of that base class.
> > >>>>
> > >>>
> > >>> The ability to change the code is one of the main points behind GPL.
> > >>> So yes, you can change the source.
> > >>>
> > >>> Just beware that if the interface is public you should try to keep
> > >>> backwards compatibility.  I grepped all of the Octave Forge for DAEFunc
> >>> and all of its subclasses [1] but couldn't find it being used so you
> >>> should be fine.
> >>>
> >>> Carnë
> >>>
> >>> [1] http://octave.org/doxygen/4.1/d9/d83/classDAEFunc.html
> >>
> >> Francesco,
> >>
> >> As Carnë's answer shows, your question is ill posed and leads to misunderstandings:
> >>
> >> of course you can change the source, the GPL license grants you this right,
> >> the real question would be whether that change would be accepted by Octave
> >> developers in the main repository or not.
> >
> >To make this more clear, who holds copyright is pointless and referring to that
> >in your question is distracting.
> >
> >The question is a technical question about the class design and functionality, not
> >a legal question about licenses and copyright.
> >
> >> c.
>
> Carlo, Carnë,
>
> sorry, my question was not well posed and thank you for making this clear to me.
> I'm not still sure we can avoid global pointers wrt the design of Octave. Let me explain why:
>
> In my dld-function I have a pointer to the octave_function provided by the user and I use it inside a  DAERHSFunc to compute residual. I use a pointer to thisDAERHSFunc when I construct an object of my class.
>
> Inside my class I have methods which allows me to interface with Sundials' types and functions. In particular, I use a lambda to pass a residual function (with fixed signature) to a function of Sundials (with fixed signature).
>
> The problem here is that I cannot use classes and methods of libinterp inside liboctave to compute residual, I can only put a forward declaration in my class.
>
> My first and actual solution is to call inside my lambda a pointer (stored in the base class) to the DAERHSFunc defined in my dld-fun, so I can call methods of class octave_function and I avoid code duplication, but I need to declare the poiner to octave_function global in my dld-function.
>
> What I was trying to do, was to store the octave_function pointer as member of my class and to pass it as a parameter when I dereference the pointer  to the DAERHSFunc  in my lambda.  But since it has incomplete type I get segmentation fault.
>
> I think I could avoid global pointers changing completely the constructor of my class, but then inheriting from DAE would be meaningless.
>
> Do you have any suggestions or do you know some workaround to this?
>
> Thank you,
>
> Francesco


Hi Francesco,

As a general

Can you provide links to lines in your code on bitbucket so we can follow more clearly what you are talking about?

Dear Carlo,

here's the link to my dld-function [1], to the header of my class [2] and its implementation [3].
In [1] line 71 there is the definition of the DAERHSFunc I call in line 230 where I construct my object.

>Are lambdas among the C++11 features that are acceptable to use in Octave 4.1?

I can compile Octave using lambdas, but as you asket I suppose that's not enough. Where can I check this?


Why is your class IDA inheriting from DAE? What methods from the base class are you actually using?

Since a dae solved by ode15i "is a" DAE and the design is pretty similar to daspk.cc, I think that it's the right place to be inside Octave. In IDA I call the constructor of the base class DAEFunc passing as argument a pointer to the DAERHSFunc and the constructors of base class base_diff_alg_eqn and base_diff_eqn. I call methods base_diff_eqn::time(), base_diff_eqn::state(), base_diff_alg_eqn::state_derivative() inside another method to initialize Ida solver and I dereference the function of the base class DAEFunc in order to compute residual ([3] line 70). 


> 2 - use the void pointer user_data to pass the 'this' pointer of the current object
>     
> static int
> IDA::res_interface (realtype tt, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
>  {
>    IDA *self = static_cast<IDA*>(user_data);
>    ...
>  }

This is similar to what I do: my lambda can't capture any parameter because the signature would change. If the lambda doesn't capture anything, I still create a closure, but  I can pass the lambda as a pointer to function to IDAInit ([3], line 79). 

I store in user_data the pointer to the DAERHSFunc I want to call:

void IDA::set_userdata(void *& ida_mem)
{
  void * userdata = &fun;
  int flag = IDASetUserData(ida_mem, userdata);
}

and then, inside a method:

auto resfun = [] (realtype t, N_Vector yy, N_Vector yp, N_Vector rr, void *user_data)
{
...
DAEFunc::DAERHSFunc *data = "" *>(user_data);
DAEFunc::DAERHSFunc pointres = *data;
ColumnVector res = (*pointres) (y0, yp0, t, ires);  
...
};

int flag = IDAInit (ida_mem, resfun, t0, yy, yp);


>3 - you can now access the non static class member methods via the pointer

This is nice, but I can't write methods that compute residual inside my class. I need to call method do_multi_index_op or feval, which are defined in libinterp. That's why I dereference pointres to call function defined in [1] line 72. 
 
What I wanted to do to avoid global pointers was to overload the constructor of DAEFunc in order to call 

ColumnVector res = (*pointres) (y0, yp0, t, ires, ida_fcn);  

where ida_fcn is a octave_function *, but octave_function is an incomplete type inside liboctave.
The same problem affects the Jacobian evaluation.

We have 4 options I think:
- find a brilliant way to evaluate residual in liboctave avoiding global pointers (passing ida_fcn in some way)
-inherit from DAE and evaluate residual completely inside the dld-function (I can write resfun as a normal function and pass it to IDAInit)
-don't inherit from DAE and evaluate residual completely inside the dld-function
-use the global pointer as daspk, dassl, dasrt and other corefcn

In these days I became quite familiar with std::function, std::function::target, std::bind, so if there is a nice way to use them we can try something magic. 

Thank you for the hints,

Francesco

 
[1] https://bitbucket.org/Francesco_Faccio/octave/src/6f04dbbe5fdf147fbd95fb3ea8901e5fd61081a7/libinterp/dldfcn/__ode15__.cc?at=default&fileviewer=file-view-default
[2]https://bitbucket.org/Francesco_Faccio/octave/src/6f04dbbe5fdf147fbd95fb3ea8901e5fd61081a7/liboctave/numeric/IDA.h?at=default&fileviewer=file-view-default
[3]https://bitbucket.org/Francesco_Faccio/octave/src/6f04dbbe5fdf147fbd95fb3ea8901e5fd61081a7/liboctave/numeric/IDA.cc?at=default&fileviewer=file-view-default

reply via email to

[Prev in Thread] Current Thread [Next in Thread]