proteus 1.9.0
C/C++/Fortran libraries
Loading...
Searching...
No Matches
ArgumentsDict.cpp
Go to the documentation of this file.
1#include "pybind11/pybind11.h"
2#include "pybind11/stl_bind.h"
3
4#define FORCE_IMPORT_ARRAY
5#include "ArgumentsDict.h"
6
7namespace xt
8{
9#if defined(__GNUC__) && !defined(__clang__)
10 namespace workaround
11 {
12 inline void complex_allocator()
13 {
14 std::allocator<int> ai;
15 std::allocator<double> ad;
16 }
17 }
18#endif
19}
20
21namespace py = pybind11;
22
23namespace
24{
25 const std::string DARRAY_DICT_NAME = "DArrayDict";
26 const std::string IARRAY_DICT_NAME = "IArrayDict";
27 const std::string DSCALAR_DICT_NAME = "DScalarDict";
28 const std::string ISCALAR_DICT_NAME = "IScalarDict";
29}
30
31namespace proteus
32{
33 namespace detail
34 {
35 template <class OS, class M>
36 OS& print_map(OS& os, const std::string& name, const M& m)
37 {
38 os << name << '{';
39 bool f = false;
40 for(const auto& kv: m)
41 {
42 if(f)
43 {
44 os << ", ";
45 }
46 os << kv.first <<": " << kv.second;
47 f = true;
48 }
49 os << '}';
50 return os;
51 }
52 }
53
54 template <class M>
55 void bind_throwing_map(py::class_<M>& cl, const std::string& name)
56 {
57 using map_type = M;
58 using key_type = typename map_type::key_type;
59 using mapped_type = typename map_type::mapped_type;
60
61 cl.def(py::init<>());
62
63 cl.def("__setitem__",
64 [](map_type& m, key_type& k, mapped_type& v)
65 {
66 m.insert_or_assign(std::move(k), std::move(v));
67 }
68 );
69
70 cl.def("__repr__",
71 [name](map_type& m)
72 {
73 std::ostringstream oss;
74 return detail::print_map(oss, name, m).str();
75 },
76 "Return the canonical representation of this map."
77 );
78
79 cl.def("__bool__",
80 [](map_type& m) -> bool
81 {
82 return !m.empty();
83 },
84 "Check wether the map is nonempty"
85 );
86
87 cl.def("__getitem__",
88 [](map_type& m, const key_type& k) -> mapped_type&
89 {
90 auto it = m.find(k);
91 if(it == m.end())
92 {
93 throw std::runtime_error(detail::key_error_message(k));
94 }
95 return it->second;
96 }
97 );
98 }
99
100 void bind_arguments_dict(py::class_<arguments_dict>& cl, const std::string& name)
101 {
102 cl.def(py::init<>());
103
104 cl.def_readwrite("darray", &arguments_dict::m_darray);
105 cl.def_readwrite("iarray", &arguments_dict::m_iarray);
106 cl.def_readwrite("dscalar", &arguments_dict::m_dscalar);
107 cl.def_readwrite("iscalar", &arguments_dict::m_iscalar);
108
109
110 cl.def("__setitem__",
111 [](arguments_dict& ad, std::string& k, xt::pyarray<int>& a)
112 {
113 ad.m_iarray.insert_or_assign(std::move(k), std::move(a));
114 });
115 cl.def("__setitem__",
116 [](arguments_dict& ad, std::string& k, xt::pyarray<double>& a)
117 {
118 ad.m_darray.insert_or_assign(std::move(k), std::move(a));
119 });
120 // IMPORTANT: keep the scalar overloads AFTER the pyarray overloads,
121 // because numpy array containing a single elements can be implicitly
122 // converted to scalars. If the scalar overload is define before the
123 // pyarray overload, it is chosen by pybind11 and the array ends up
124 // in the wrong dictionary.
125 cl.def("__setitem__",
126 [](arguments_dict& ad, std::string& k, int i)
127 {
128 ad.m_iscalar.insert_or_assign(std::move(k), std::move(i));
129 });
130 cl.def("__setitem__",
131 [](arguments_dict& ad, std::string& k, double d)
132 {
133 ad.m_dscalar.insert_or_assign(std::move(k), std::move(d));
134 });
135 cl.def("__repr__",
136 [name](arguments_dict& ad)
137 {
138 std::ostringstream oss;
139 oss << name << "{\n";
140 oss << " " << "m_darray: ";
141 detail::print_map(oss, DARRAY_DICT_NAME, ad.m_darray);
142 oss << "\n " << "m_iarray: ";
143 detail::print_map(oss, IARRAY_DICT_NAME, ad.m_iarray);
144 oss << "\n " << "m_dscalar: ";
145 detail::print_map(oss, DSCALAR_DICT_NAME, ad.m_dscalar);
146 oss << "\n " << "m_iscalar: ";
147 detail::print_map(oss, ISCALAR_DICT_NAME, ad.m_iscalar);
148 oss << "\n}";
149 return oss.str();
150 });
151 }
152}
153
154PYBIND11_MODULE(cArgumentsDict, m)
155{
159
160 xt::import_numpy();
161
162 using dpyarray_dict = pyarray_dict<std::string, double>;
163 using ipyarray_dict = pyarray_dict<std::string, int>;
164 using dscalar_dict = scalar_dict<std::string, double>;
165 using iscalar_dict = scalar_dict<std::string, int>;
166
167 py::class_<dpyarray_dict> dad(m, DARRAY_DICT_NAME.c_str());
168 proteus::bind_throwing_map(dad, DARRAY_DICT_NAME.c_str());
169
170 py::class_<ipyarray_dict> iad(m, IARRAY_DICT_NAME.c_str());
171 proteus::bind_throwing_map(iad, IARRAY_DICT_NAME.c_str());
172
173 py::class_<dscalar_dict> dsd(m, DSCALAR_DICT_NAME.c_str());
174 proteus::bind_throwing_map(dsd, DSCALAR_DICT_NAME.c_str());
175
176 py::class_<iscalar_dict> isd(m, ISCALAR_DICT_NAME.c_str());
177 proteus::bind_throwing_map(isd, ISCALAR_DICT_NAME.c_str());
178
179 py::class_<arguments_dict> ad(m, "ArgumentsDict");
180 proteus::bind_arguments_dict(ad, "ArgumentsDict");
181}
182
PYBIND11_MODULE(cADR, m)
Definition ADR.cpp:21
Double v
Definition Headers.h:95
OS & print_map(OS &os, const std::string &name, const M &m)
std::string key_error_message(const std::string &key)
Definition ADR.h:19
void bind_throwing_map(py::class_< M > &cl, const std::string &name)
throwing_map< K, T > scalar_dict
throwing_map< K, xt::pyarray< T > > pyarray_dict
double f(const double &g, const double &h, const double &hZ)
Definition SW2DCV.h:58
void bind_arguments_dict(py::class_< arguments_dict > &cl, const std::string &name)
pyarray_dict< std::string, double > m_darray
scalar_dict< std::string, int > m_iscalar
pyarray_dict< std::string, int > m_iarray
scalar_dict< std::string, double > m_dscalar