File: pythontests.py

package info (click to toggle)
dune-common 2.10.0-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,824 kB
  • sloc: cpp: 52,256; python: 3,979; sh: 1,658; makefile: 17
file content (89 lines) | stat: -rw-r--r-- 2,725 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
# SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception

from io import StringIO
from numpy import array

import os
# enable DUNE_SAVE_BUILD to test various output options
os.environ['DUNE_LOG_LEVEL'] = 'info'
os.environ['DUNE_SAVE_BUILD'] = 'console'

classACode="""
struct MyClassA {
  MyClassA(int a,int b) : a_(a), b_(b) {}
  double b() { return b_; }
  int a_,b_;
};
"""
classBCode="""
#include <iostream>
#include <cmath>
#include <numeric>
#include <dune/python/common/numpyvector.hh>
template <class T> struct MyClassB {
  // the following fails to work correctly
  // MyClassB(T &t, int p, const Dune::Python::NumPyVector<double> &b)
  // - with 'const NumPyVector<double> b_;':  call to deleter ctor
  // - with 'const NumPyVector<double> &b_;': segfaults (this is expected
  //        since array_t->NumPyArray in the __init__ function is explicit and
  //        leads to dangling reference)
  // The following has to be used:
  MyClassB(T &t, int p, pybind11::array_t< double >& b)
  : a_(std::pow(t.a_,p)), b_(b) {}
  double b() { return std::accumulate(b_.begin(),b_.end(),0.); }
  int a_;
  const Dune::Python::NumPyVector<double> b_;
};
"""
runCode="""
#include <iostream>
template <class T> int run(T &t) {
  return t.a_ * t.b();
}
"""

runVec="""
#include <dune/python/common/numpyvector.hh>
template <class T>
void run(pybind11::array_t< T >& a)
{
  Dune::Python::NumPyVector< T > x( a );
  for( size_t i=0; i<x.size(); ++i )
    x[ i ] += i;
}
"""

def test_numpyvector():
    """
    Test correct exchange of numpy arrays to C++ side.
    """
    from dune.generator.algorithm import run
    x = array([0.]*100)
    run("run",StringIO(runVec),x)
    for i in range(len(x)):
        assert x[i] == float(i)

def test_class_export():
    from dune.generator.importclass import load
    from dune.generator.algorithm   import run
    from dune.typeregistry import generateTypeName
    a = 2.
    x = array([2.]*10)
    cls = load("MyClassA",StringIO(classACode),10,20)
    assert run("run",StringIO(runCode),cls) == 10*20
    clsName, _ = generateTypeName("MyClassB",cls)
    cls = load(clsName,StringIO(classBCode),cls,2,x)
    assert run("run",StringIO(runCode),cls) == 10**2*10*a
    x[:] = array([3.]*10)[:]
    assert run("run",StringIO(runCode),cls) == 10**2*10*3
    # the following does not work
    x = array([4.]*10)
    # the 'B' class still keeps the old vector 'x' alive
    assert run("run",StringIO(runCode),cls) == 10**2*10*3

if __name__ == "__main__":
    from dune.packagemetadata import getDunePyDir
    _ = getDunePyDir()
    test_class_export()
    test_numpyvector()