ppap4lmp  0.7.2
element.cpp
Go to the documentation of this file.
1 
9 #include "element.h"
10 #include "updater.h"
11 #include "../utils/join.h"
12 #include "../utils/message.h"
13 #include "../utils/pyargs_to_vec.h"
14 #include "../utils/runtime_error.h"
15 
16 namespace ut = utils;
17 
19 
20 /* ------------------------------------------------------------------ */
21 
23 {
26  omp_init_lock(&omp_lock);
27 }
28 
29 /* ------------------------------------------------------------------ */
30 
32 {
33  #pragma omp atomic
34  n_bookings++;
35 }
36 
37 /* ------------------------------------------------------------------ */
38 
40 {
41  omp_set_lock(&omp_lock);
42 
43  n_bookings--;
44 
45  if (n_bookings == 0)
46  {
47  if (data.is_array())
48  {
49  data.get_ref<Json::array_t&>().clear();
50  data.get_ref<Json::array_t&>().shrink_to_fit();
51  data = nullptr;
52  }
53  else
54  {
55  data.clear();
56  data = nullptr;
57  }
58 
59  update_keys();
60 
61  auto shared_this = shared_from_this();
62 
63  for (const auto &pair : update_chain)
64  {
65  if (pair.first == shared_this)
66  {
67  pair.second->remove_from_skippable_elementids(elementid);
68  }
69  }
70 
71  ut::log("Data-" + std::to_string(elementid) + " has been deleted");
72  }
73  else if (n_bookings < 0)
74  {
76  "Data-" + std::to_string(elementid) + " was used illegally");
77  }
78 
79  omp_unset_lock(&omp_lock);
80 }
81 
82 /* ------------------------------------------------------------------ */
83 
85  const ShPtr<Updater> &upd)
86 {
87  omp_set_lock(&omp_lock);
88 
89  upd->compute(shared_from_this(), elementid, data);
90 
91  omp_unset_lock(&omp_lock);
92 }
93 
94 /* ------------------------------------------------------------------ */
95 
97  const Json &key_)
98 {
99  const Vec<Str> keys = key_.is_array() ? key_ : Json::array({key_});
100 
101  Vec<std::pair<Str,int>> distances;
102  int distance_from_begin_ex = 0;
103 
104  for (auto it = datakeys.cbegin(); it != datakeys.cend(); ++it)
105  {
106  if (std::find(keys.cbegin(), keys.cend(), *it) != keys.cend())
107  {
108  int distance_from_begin = std::distance(datakeys.cbegin(), it);
109  distances.push_back(std::make_pair(
110  *it, distance_from_begin - distance_from_begin_ex));
111  distance_from_begin_ex = distance_from_begin;
112  }
113  }
114 
115  return distances;
116 }
117 
118 /* ------------------------------------------------------------------ */
119 
121  const Json &name)
122 {
123  if (name != nullptr)
124  {
125  ut::runtime_error("Rejection of non-null Json");
126  }
127 
128  return shared_from_this();
129 }
130 
131 /* ------------------------------------------------------------------ */
132 
134  const Json &name)
135 {
136  if (name != nullptr)
137  {
138  ut::runtime_error("Rejection of non-null Json");
139  }
140 
141  return shared_from_this();
142 }
143 
144 /* ------------------------------------------------------------------ */
145 
147  const Str &classname)
148 {
149  #pragma omp critical (set_accessing_classname)
150  {
151  accessing_classname = classname;
152  }
153 }
154 
155 /* ------------------------------------------------------------------ */
156 
158  const ShPtr<Updater> &upd)
159 {
160  auto gen = upd->get_ext_generator();
161 
162  if (gen)
163  {
164  merge_update_chain(gen->get_update_chain());
165  }
166 
167  update_chain.push_back(UpdatePair(shared_from_this(), upd));
168 
169  return shared_from_this();
170 }
171 
172 /* ------------------------------------------------------------------ */
173 
175 {
176  return data;
177 }
178 
179 /* ------------------------------------------------------------------ */
180 
182 {
183  return Set<Str>(datakeys.begin(), datakeys.end());
184 }
185 
186 /* ------------------------------------------------------------------ */
187 
189 {
190  const auto pairs_key_and_distance = get_distances_between_keys(key_);
191 
192  auto reduced_data = Json::array();
193 
194  if (data.is_array())
195  {
196  reduced_data.get_ref<Json::array_t&>().reserve(data.size());
197  }
198 
199  for (const auto &d : data.is_array() ? data : Json::array({data}))
200  {
201  reduced_data.push_back({});
202  auto &back = reduced_data.back();
203  auto it_item = d.begin();
204 
205  for (const auto &pair : pairs_key_and_distance)
206  {
207  std::advance(it_item, pair.second);
208  back[pair.first] = *it_item;
209  }
210  }
211 
212  return data.is_array() ? reduced_data : reduced_data.front();
213 }
214 
215 /* ------------------------------------------------------------------ */
216 
217 template <typename T>
219  T &array,
220  const Str &key)
221 {
222  array.resize(data.is_array() ? data.size() : 1);
223 
224  const auto key_position = std::distance(
225  datakeys.cbegin(), std::find(datakeys.cbegin(), datakeys.cend(), key));
226 
227  int index = 0;
228 
229  for (const auto &d : data.is_array() ? data : Json::array({data}))
230  {
231  array(index++) = *std::next(d.cbegin(), key_position);
232  }
233 }
234 
235 /* ------------------------------------------------------------------ */
236 
237 template <typename T>
239  T &array,
240  const Vec<Str> &keys)
241 {
242  array.resize(data.is_array() ? data.size() : 1, keys.size());
243 
244  Vec<std::pair<int,int>> pairs_distance_and_icol;
245  for (const auto &pair : get_distances_between_keys(keys))
246  {
247  pairs_distance_and_icol.push_back(std::make_pair(
248  pair.second,
249  std::distance(
250  keys.cbegin(), std::find(keys.cbegin(), keys.cend(), pair.first))
251  ));
252  }
253 
254  int irow = 0;
255 
256  for (const auto &d : data.is_array() ? data : Json::array({data}))
257  {
258  auto it_item = d.begin();
259 
260  for (const auto &pair : pairs_distance_and_icol)
261  {
262  std::advance(it_item, pair.first);
263  array(irow, pair.second) = *it_item;
264  }
265 
266  irow++;
267  }
268 }
269 
270 /* ------------------------------------------------------------------ */
271 
273 {
274  datakeys.clear();
275 
276  for (const auto &el : (data.is_array() ? data.front() : data).items())
277  {
278  datakeys.push_back(el.key());
279  }
280 }
281 
282 /* ------------------------------------------------------------------ */
283 
285  const Json &key_)
286 {
287  const Vec<Str> keys = key_.is_array() ? key_ : Json::array({key_});
288  Vec<Str> missing_keys;
289 
290  for (const auto &key : keys)
291  {
292  if (std::find(datakeys.cbegin(), datakeys.cend(), key) == datakeys.cend())
293  {
294  missing_keys.push_back(key);
295  }
296  }
297 
298  if (!missing_keys.empty())
299  {
300  std::sort(missing_keys.begin(), missing_keys.end());
301 
302  Str msg = "Missing key(s) '" + ut::join(missing_keys, "', '") + "'";
303 
304  if (!accessing_classname.empty())
305  {
306  msg += " in " + accessing_classname;
307  }
308 
309  ut::runtime_error(msg);
310  }
311 }
312 
313 /* ------------------------------------------------------------------ */
314 
316  const Json &key_)
317 {
318  const Vec<Str> keys = key_.is_array() ? key_ : Json::array({key_});
319 
320  for (const auto &key : keys)
321  {
322  if (std::find(datakeys.cbegin(), datakeys.cend(), key) == datakeys.cend())
323  {
324  return false;
325  }
326  }
327 
328  return true;
329 }
330 
331 /* functions for Python --------------------------------------------- */
332 
334 {
335  init_for_python();
336 
337  return data;
338 }
339 
340 /* ------------------------------------------------------------------ */
341 
343 {
344  init_for_python();
345 
346  return get_keys();
347 }
348 
349 /* ------------------------------------------------------------------ */
350 
352  const Str &key)
353 {
354  init_for_python();
355 
356  check_required_keys(key);
357 
358  ArrayXi array;
359  make_1darray_from_data(array, key);
360 
361  return array;
362 }
363 
364 /* ------------------------------------------------------------------ */
365 
367  const Str &key)
368 {
369  init_for_python();
370 
371  check_required_keys(key);
372 
373  ArrayXd array;
374  make_1darray_from_data(array, key);
375 
376  return array;
377 }
378 
379 /* ------------------------------------------------------------------ */
380 
382  const py::args &args)
383 {
384  init_for_python();
385 
386  Vec<Str> keys;
387  ut::pyargs_to_vec(args, keys);
388 
389  check_required_keys(keys);
390 
391  ArrayXXi array;
392  make_2darray_from_data(array, keys);
393 
394  return array;
395 }
396 
397 /* ------------------------------------------------------------------ */
398 
400  const py::args &args)
401 {
402  init_for_python();
403 
404  Vec<Str> keys;
405  ut::pyargs_to_vec(args, keys);
406 
407  check_required_keys(keys);
408 
409  ArrayXXd array;
410  make_2darray_from_data(array, keys);
411 
412  return array;
413 }
414 
415 /* ------------------------------------------------------------------ */
416 
418 {
419  try
420  {
421  generate_data();
422  }
423  catch (std::runtime_error &e)
424  {
425  // NOTE: Error message can also be seen as Python's exception.
426  ut::log("ERROR - " + Str(e.what()));
427  }
428 }
ArrayXd get_1d_float_py(const Str &key)
Get float values stored in Element::data of this object as a one-dimensional Numpy-Array.
Definition: element.cpp:366
Set< Str > get_keys_py()
Get keys of the data of this object.
Definition: element.cpp:342
Str accessing_classname
Definition: element.h:79
This file has a definition of Element class, which is one of the cores of this program.
int elementid
Definition: element.h:60
Vec< Str > datakeys
Definition: element.h:74
ShPtr< Element > ElPtr
An alias for a shared pointer of Element class.
Definition: element.h:378
Json make_reduced_data(const Json &key_)
Get reduced data of this object.
Definition: element.cpp:188
Set< Str > get_keys()
Get keys of the data of this object.
Definition: element.cpp:181
const Json & get_data()
Get a reference to data of this object.
Definition: element.cpp:174
int n_bookings
Definition: element.h:54
Eigen::Array< double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > ArrayXXd
ArrayXXd is an alias for a two-dimensional array of float numbers.
Definition: eigen.h:32
void make_2darray_from_data(T &array, const Vec< Str > &keys)
Extract values of properties in data as a two-dimensional Eigen-Array.
Definition: element.cpp:238
void check_required_keys(const Json &key_)
Check if this object has required key(s).
Definition: element.cpp:284
const Json & get_data_py()
Get a reference to data of this object.
Definition: element.cpp:333
omp_lock_t omp_lock
Definition: element.h:86
ArrayXXd get_2d_float_py(const py::args &args)
Get float values stored in Element::data of this object as a two-dimensional Numpy-Array.
Definition: element.cpp:399
Json data
Definition: element.h:69
Vec< std::pair< Str, int > > get_distances_between_keys(const Json &key_)
To speed up accessing values in Json.
Definition: element.cpp:96
std::string Str
Str is an alias for string.
Definition: std.h:21
Element()
Constructor of Element class.
Definition: element.cpp:22
virtual ShPtr< Element > get_element(const Json &name=nullptr) override
Get this object as a shared pointer of Element class.
Definition: element.cpp:120
std::pair< ShPtr< Element >, ShPtr< Updater > > UpdatePair
UpdatePair is a pair of shared pointer of Element class and Updater class.
Definition: generator.h:27
nlohmann::json Json
Json is an alias for nlohmann::json.
Definition: json.h:22
Eigen::Array< int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor > ArrayXXi
ArrayXXi is an alias for a two-dimensional integer array.
Definition: eigen.h:22
void generate_data()
Hello to this Generator object.
Definition: generator.cpp:67
std::unordered_set< T > Set
Set is an alias for unordered set (same as set in Python).
Definition: std.h:49
void merge_update_chain(const Vec< UpdatePair > &new_chain)
Definition: generator.cpp:15
void update_keys()
Update datakeys. This method must be called after setting new properties to data. ...
Definition: element.cpp:272
virtual ShPtr< Generator > get_generator(const Json &name=nullptr) override
Get this object as a shared pointer of Generator class.
Definition: element.cpp:133
void pyargs_to_vec(const py::args &args, Vec< T > &vec)
Convert a py::args (a variable number arguments) object to a Vec object.
std::vector< T > Vec
Vec is an alias for vector (same as list in Python).
Definition: std.h:27
void decrement_bookings()
Definition: element.cpp:39
ShPtr< Element > append_updater(const ShPtr< Updater > &upd)
Append an Updater object to this Element object: the only way to extend an updating process associate...
Definition: element.cpp:157
void runtime_error(const Str &msg)
Raise (for Python) and throw (for C++) a runtime error.
Eigen::Array< int, Eigen::Dynamic, 1 > ArrayXi
ArrayXi is an alias for a column array of integers.
Definition: eigen.h:37
static int n_element_instances
Definition: element.h:47
void update_data(const ShPtr< Updater > &upd)
Definition: element.cpp:84
Str join(const Vec< Str > &strs, const Str &jointer)
Mimicking Python&#39;s join.
Definition: join.cpp:14
void log(const Str &msg)
Logging a message.
Definition: message.cpp:29
bool check_optional_keys(const Json &key_)
Check if this object has optional key(s).
Definition: element.cpp:315
Namespace for utility functions.
Definition: join.h:14
void init_for_python()
Definition: element.cpp:417
ArrayXXi get_2d_int_py(const py::args &args)
Get integer values stored in Element::data of this object as a two-dimensional Numpy-Array.
Definition: element.cpp:381
Eigen::Array< double, Eigen::Dynamic, 1 > ArrayXd
ArrayXd is an alias for a column array of float numbers.
Definition: eigen.h:42
Vec< UpdatePair > update_chain
Definition: generator.h:52
virtual void accessed_by_instance_of(const Str &classname) override
Set class name of an instance calling Element::check_required_keys.
Definition: element.cpp:146
std::shared_ptr< T > ShPtr
ShPtr is an alias for shared pointer.
Definition: std.h:16
void make_1darray_from_data(T &array, const Str &key)
Extract values of a property in data as a one-dimensional Eigen-Array.
Definition: element.cpp:218
void increment_bookings()
Definition: element.cpp:31
ArrayXi get_1d_int_py(const Str &key)
Get integer values stored in Element::data of this object as a one-dimensional Numpy-Array.
Definition: element.cpp:351
This file has a definition of Updater class, which is one of the cores of this program.