proteus  1.8.1
C/C++/Fortran libraries
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 
7 namespace 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 
21 namespace py = pybind11;
22 
23 namespace
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 
31 namespace 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 
154 PYBIND11_MODULE(cArgumentsDict, m)
155 {
156  using proteus::pyarray_dict;
157  using proteus::scalar_dict;
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 
proteus::detail::print_map
OS & print_map(OS &os, const std::string &name, const M &m)
Definition: ArgumentsDict.cpp:36
proteus::bind_arguments_dict
void bind_arguments_dict(py::class_< arguments_dict > &cl, const std::string &name)
Definition: ArgumentsDict.cpp:100
proteus::arguments_dict::m_iscalar
scalar_dict< std::string, int > m_iscalar
Definition: ArgumentsDict.h:74
PYBIND11_MODULE
PYBIND11_MODULE(cArgumentsDict, m)
Definition: ArgumentsDict.cpp:154
proteus::arguments_dict::m_darray
pyarray_dict< std::string, double > m_darray
Definition: ArgumentsDict.h:71
v
Double v
Definition: Headers.h:95
proteus::pyarray_dict
throwing_map< K, xt::pyarray< T > > pyarray_dict
Definition: ArgumentsDict.h:64
proteus::arguments_dict::m_iarray
pyarray_dict< std::string, int > m_iarray
Definition: ArgumentsDict.h:72
proteus::arguments_dict::m_dscalar
scalar_dict< std::string, double > m_dscalar
Definition: ArgumentsDict.h:73
xt
Definition: AddedMass.cpp:7
proteus::detail::key_error_message
std::string key_error_message(const std::string &key)
Definition: ArgumentsDict.h:110
proteus
Definition: ADR.h:17
proteus::f
double f(const double &g, const double &h, const double &hZ)
Definition: SW2DCV.h:58
proteus::arguments_dict
Definition: ArgumentsDict.h:70
proteus::scalar_dict
throwing_map< K, T > scalar_dict
Definition: ArgumentsDict.h:67
proteus::bind_throwing_map
void bind_throwing_map(py::class_< M > &cl, const std::string &name)
Definition: ArgumentsDict.cpp:55
ArgumentsDict.h