Expression with C-Code, pass array TypeMap

Asked by jenom on 2013-04-24

Hello,

I want to create an expression using C code which needs a two dimensional array as a parameter. Therefore I wanted to include a setter method, which handles this parameter array. Is there a way to achieve this?

My C code looks as follows now:
    code = '''
        class MyFunc : public Expression {

        public:
            double** _coeffs;
            int _nDomains;
            int _nCoeffs;

            MyFunc() : Expression() { }

            void setCoeffs(int nDomains, int nCoeffs, double** coeffs) {

            }

            void eval(Array<double>& values, const Array<double>& x,
                      const ufc::cell& c) const {
                if (x[1] <= 1./3.)
                    values[0] = 0;
                else if (x[1] <= 2./3. && x[1] >= 1./3.)
                    values[0] = 1;
                else if (x[1] >= 2./3.)
                    values[0] = 2;
            }
        };
        '''

What I need is a way to call the setCoeffs method with a numpy array. The eval function is dummy for now.

Thanks for the help,
Johannes

edit: nDomains and nCoeffs represent the dimensions of the array.

Question information

Language:
English Edit question
Status:
Solved
For:
DOLFIN Edit question
Assignee:
No assignee Edit question
Solved by:
Johan Hake
Solved:
2013-05-06
Last query:
2013-05-06
Last reply:
2013-04-29
Johan Hake (johan-hake) said : #1

Does all of your sub array have the same length? If so I would suggest you use an

  const Array<double>& coeffs

as argument and think of it as a flatten array. This could then be used to create your _coeffs variable.

Jan Blechta (blechta) said : #2

Pack values to contiguous numpy array of shape (n,) and use dolfin::Array<double> on C++ side. These types are mapped between selves.

jenom (jenom) said : #3

Thank you very much for your fast response. I tried your suggestion #2 as in the c++ part it is packed anyhow. But when I call the "setCoeffs(Array<double>& coeffs)" now with "setCoeffs(coeffs.flatten())", where coeffs is a float64 ndarray, I get a TypeError

TypeError: in method 'MyFunc_setCoeffs', argument 2 of type 'dolfin::Array< double > &'

unfortunately it does not tell, what it is expecting.

Jan Blechta (blechta) said : #4

On Fri, 26 Apr 2013 12:46:15 -0000
jenom <email address hidden> wrote:
> Question #227358 on DOLFIN changed:
> https://answers.launchpad.net/dolfin/+question/227358
>
> Status: Answered => Open
>
> jenom is still having a problem:
> Thank you very much for your fast response. I tried your suggestion #2
> as in the c++ part it is packed anyhow. But when I call the
> "setCoeffs(Array<double>& coeffs)" now with
> "setCoeffs(coeffs.flatten())", where coeffs is a float64 ndarray, I
> get a TypeError
>
> TypeError: in method 'MyFunc_setCoeffs', argument 2 of type
> 'dolfin::Array< double > &'
>
> unfortunately it does not tell, what it is expecting.
>

This works:

code = '''
        class MyFunc : public Expression {

        public:
            double** _coeffs;
            int _nDomains;
            int _nCoeffs;

            MyFunc() : Expression() { }

            void setCoeffs(int nDomains, int nCoeffs, const Array<double>& coeffs) {
                std::cout << nDomains << nCoeffs << coeffs.str(true) << std::endl;
            }

            void eval(Array<double>& values, const Array<double>& x,
                      const ufc::cell& c) const {
                if (x[1] <= 1./3.)
                    values[0] = 0;
                else if (x[1] <= 2./3. && x[1] >= 1./3.)
                    values[0] = 1;
                else if (x[1] >= 2./3.)
                    values[0] = 2;
            }
        };
        '''

expr = Expression(code)
expr.setCoeffs(42, 43, numpy.array([44.0, 45.0]))

Best Johan Hake (johan-hake) said : #5

The reason Jan's code work is that the general typemap between Array and NumPy arrays only works for const Array references.

Johan

jenom (jenom) said : #6

Thanks Johan Hake, that solved my question.

jenom (jenom) said : #7

Thank you both for your fast help. Programming in two languages at the same time with somewhat different concepts can be confusing ;). I solved my problem thanks to your help.