PFASST++
particle_util_impl.hpp
Go to the documentation of this file.
1 #include "particle_util.hpp"
2 
3 #include <algorithm>
4 #include <cassert>
5 #include <cmath>
6 #include <functional>
7 #include <type_traits>
8 using namespace std;
9 
10 #include <pfasst/globals.hpp>
11 #include <pfasst/logging.hpp>
12 
13 
14 namespace pfasst
15 {
16  namespace examples
17  {
18  namespace boris
19  {
20  template<typename precision>
21  inline static vector<precision> cloud_component_factory(const size_t num_particles, const size_t dim)
22  {
23  vector<precision> out(num_particles * dim, precision(0.0));
24  return out;
25  }
26 
27 
28  template<typename precision>
29  inline static void zero(vector<precision>& data)
30  {
31  std::fill(data.begin(), data.end(), precision(0.0));
32  }
33 
34  template<typename precision>
35  inline static void zero(shared_ptr<vector<precision>>& data)
36  {
37  zero(*data.get());
38  }
39 
40 
41  template<typename precision>
42  inline static vector<precision> cross_prod(const vector<precision>& first, const vector<precision>& second)
43  {
44  if (first.size() == 3 && first.size() == second.size()) {
45  vector<precision> result(3, precision(0.0));
46  cross_prod_1part<precision>(first.cbegin(), second.cbegin(), result.begin());
47  return result;
48  } else {
49  return cross_prod_npart(first, second);
50  }
51  }
52 
53  template<typename precision>
54  inline static void cross_prod_1part(typename vector<precision>::const_iterator __first,
55  typename vector<precision>::const_iterator __second,
56  typename vector<precision>::iterator __result)
57  {
58  __result[0] = __first[1] * __second[2] - __first[2] * __second[1];
59  __result[1] = __first[2] * __second[0] - __first[0] * __second[2];
60  __result[2] = __first[0] * __second[1] - __first[1] * __second[0];
61  }
62 
63  template<typename precision>
64  inline static vector<precision> cross_prod_npart(const vector<precision>& first, const vector<precision>& second)
65  {
66  assert(first.size() % 3 == 0 && second.size() % 3 == 0); // make sure the particles have 3 spacial dimensions
67  assert(first.size() == second.size() || second.size() == 3);
68  const size_t npart = first.size() / 3;
69  vector<precision> dest(first.size(), precision(0.0));
70  if (first.size() == second.size()) {
71  for (size_t p = 0; p < npart; ++p) {
72  cross_prod_1part<precision>(first.cbegin() + (p * 3), second.cbegin() + (p * 3), dest.begin() + (p * 3));
73  }
74  } else if (second.size() == 3) {
75  for (size_t p = 0; p < npart; ++p) {
76  cross_prod_1part<precision>(first.cbegin() + (p * 3), second.cbegin(), dest.begin() + (p * 3));
77  }
78  }
79  return dest;
80  }
81 
82 
83  template<typename precision>
84  inline static vector<precision> kronecker(const vector<precision>& first,
85  const vector<precision>& second)
86  {
87  const size_t npart = first.size();
88  const size_t ndim = second.size();
89  vector<precision> result(npart * ndim, precision(0.0));
90  for (size_t p = 0; p < npart; ++p) {
91  for (size_t d = 0; d < ndim; ++d) {
92  result[p * ndim + d] = first[p] * second[d];
93  }
94  }
95  return result;
96  }
97 
98 
99  template<typename precision>
100  inline static vector<precision> cmp_wise_mul(const vector<precision>& first, const vector<precision>& second)
101  {
102  assert(first.size() == second.size());
103  vector<precision> out(first.size(), precision(0.0));
104  transform(first.cbegin(), first.cend(), second.cbegin(), out.begin(), std::multiplies<precision>());
105  return out;
106  }
107 
108  template<typename precision>
109  inline static vector<precision> cmp_wise_div(const vector<precision>& first, const vector<precision>& second)
110  {
111  assert(first.size() == second.size());
112  vector<precision> out(first.size(), precision(0.0));
113  transform(first.cbegin(), first.cend(), second.cbegin(), out.begin(), std::divides<precision>());
114  return out;
115  }
116 
117 
118  template<typename precision>
119  inline static precision max(const vector<precision>& data)
120  {
121  return *max_element(data.cbegin(), data.cend());
122  }
123 
124  template<typename precision>
125  inline static precision max_abs(const vector<precision>& data)
126  {
127  return fabs(*max_element(data.cbegin(), data.cend(), [](const precision& a, const precision& b) { return fabs(a) < fabs(b); }));
128  }
129 
130 
131  template<typename precision>
132  inline static precision norm_sq(const vector<precision>& data)
133  {
134  auto norm = norm_sq<precision>(data.cbegin(), data.cend());
135  return norm;
136  }
137 
138  template<typename precision>
139  inline static precision norm_sq(typename vector<precision>::const_iterator __first,
140  typename vector<precision>::const_iterator __second)
141  {
142  return inner_product(__first, __second, __first, precision(0.0));
143  }
144 
145  template<typename precision>
146  inline static vector<precision> norm_sq_npart(const vector<precision>& data, const size_t npart)
147  {
148  assert(data.size() % npart == 0);
149  const size_t dim = data.size() / npart;
150  vector<precision> norm(npart, precision(0.0));
151  for (size_t p = 0; p < npart; ++p) {
152  norm[p] = norm_sq<precision>(data.cbegin() + (p * dim), data.cbegin() + ((p+1) * dim));
153  }
154  return norm;
155  }
156 
157 
158  template<typename precision>
159  inline static precision norm0(const vector<precision>& data)
160  {
161  return norm0<precision>(data.cbegin(), data.cend());
162  }
163 
164  template<typename precision>
165  inline static precision norm0(typename vector<precision>::const_iterator __first,
166  typename vector<precision>::const_iterator __second)
167  {
168  return sqrt(inner_product(__first, __second, __first, precision(0.0)));
169  }
170 
171  template<typename precision>
172  inline static vector<precision> norm0_npart(const vector<precision>& data, const size_t npart)
173  {
174  assert(data.size() % npart == 0);
175  const size_t dim = data.size() / npart;
176  vector<precision> norm(npart, precision(0.0));
177  for (size_t p = 0; p < npart; ++p) {
178  norm[p] = norm0<precision>(data.cbegin() + (p * dim), data.cend() + ((p+1) * dim));
179  }
180  return norm;
181  }
182 
183 
185  // OPERATORS: ADD
186  template<typename precision>
187  inline vector<precision> operator+(const vector<precision>& first, const vector<precision>& second)
188  {
189  vector<precision> dest;
190  if (first.size() == second.size()) {
191  dest.resize(first.size());
192  std::transform(first.cbegin(), first.cend(), second.cbegin(), dest.begin(), std::plus<precision>());
193  } else if (first.size() % 3 == 0 && second.size() == 3) {
194  dest.resize(first.size());
195  for (size_t p = 0; p < first.size() / 3; ++p) {
196  std::transform(first.cbegin() + (p * 3), first.cbegin() + ((p+1) * 3),
197  second.cbegin(), dest.begin() + (p * 3), std::plus<precision>());
198  }
199  } else {
200  // try other way round
201  // ATTENTION! recursion
202  ML_LOG(WARNING, "Commutativity of addition primaly implemented other way round."
203  << " You should switch to avoid unneccessary function calls.");
204  dest = second + first;
205  }
206  return dest;
207  }
208 
209  template<typename precision, typename ValueT>
210  inline vector<precision> operator+(const vector<precision>& vec, const ValueT& value)
211  {
212  static_assert(is_arithmetic<ValueT>::value, "");
213  vector<precision> dest(vec);
214  dest += value;
215  return dest;
216  }
217 
218  template<typename precision, typename ValueT>
219  inline vector<precision> operator+(const ValueT& value, const vector<precision>& vec)
220  {
221  static_assert(is_arithmetic<ValueT>::value, "");
222  ML_LOG(WARNING, "Commutativity of addition primaly implemented other way round."
223  << " You should switch to avoid unneccessary function calls.");
224  return vec + value;
225  }
226  // OPERATORS: ADD
228 
230  // OPERATORS: INPLACE-ADD
231  template<typename precision>
232  inline vector<precision>& operator+=(vector<precision>& first, const vector<precision>& second)
233  {
234  if (first.size() == second.size()) {
235  transform(first.cbegin(), first.cend(), second.cbegin(), first.begin(), std::plus<precision>());
236  } else if (first.size() % 3 == 0 && second.size() == 3) {
237  for (size_t p = 0; p < first.size() / 3; ++p) {
238  std::transform(first.cbegin() + (p * 3), first.cbegin() + ((p+1) * 3),
239  second.cbegin(), first.begin() + (p * 3), std::plus<precision>());
240  }
241  } else if (first.size() == 3 && second.size() % 3 == 0) {
242  for (size_t p = 0; p < first.size() / 3; ++p) {
243  std::transform(first.cbegin(), first.cend(), second.cbegin() + (p * 3),
244  first.begin(), std::plus<precision>());
245  }
246  }
247  return first;
248  }
249 
250  template<typename precision, typename ValueT>
251  inline vector<precision>& operator+=(vector<precision>& vec, const ValueT& value)
252  {
253  static_assert(is_arithmetic<ValueT>::value, "");
254  for (auto&& elem : vec) {
255  elem += value;
256  }
257  return vec;
258  }
259  // OPERATORS: INPLACE-ADD
261 
263  // OPERATORS: MINUS
264  template<typename precision>
265  inline vector<precision> operator-(const vector<precision>& first, const vector<precision>& second)
266  {
267  vector<precision> dest;
268  if (first.size() == second.size()) {
269  dest.resize(first.size());
270  std::transform(first.cbegin(), first.cend(), second.cbegin(), dest.begin(), std::minus<precision>());
271  } else if (first.size() % 3 == 0 && second.size() == 3) {
272  dest.resize(first.size());
273  for (size_t p = 0; p < first.size() / 3; ++p) {
274  std::transform(first.cbegin() + (p * 3), first.cbegin() + ((p+1) * 3), second.cbegin(),
275  dest.begin() + (p * 3), std::minus<precision>());
276  }
277  } else if (first.size() == 3 && second.size() % 3 == 0) {
278  dest.resize(first.size());
279  for (size_t p = 0; p < first.size() / 3; ++p) {
280  std::transform(first.cbegin(), first.cend(), second.cbegin() + (p * 3),
281  dest.begin() + (p * 3), std::minus<precision>());
282  }
283  }
284  return dest;
285  }
286 
287  template<typename precision, typename ValueT>
288  inline vector<precision> operator-(const vector<precision>& vec, const ValueT& value)
289  {
290  static_assert(is_arithmetic<ValueT>::value, "");
291  vector<precision> dest(vec);
292  dest -= value;
293  return dest;
294  }
295  // OPERATORS: MINUS
297 
299  // OPERATORS: INPLACE-MINUS
300  template<typename precision>
301  inline vector<precision>& operator-=(vector<precision>& first, const vector<precision>& second)
302  {
303  if (first.size() == second.size()) {
304  transform(first.cbegin(), first.cend(), second.cbegin(), first.begin(), std::minus<precision>());
305  } else if (first.size() % 3 == 0 && second.size() == 3) {
306  for (size_t p = 0; p < first.size() / 3; ++p) {
307  std::transform(first.cbegin() + (p * 3), first.cbegin() + ((p+1) * 3),
308  second.cbegin(), first.begin() + (p * 3), std::minus<precision>());
309  }
310  } else if (first.size() == 3 && second.size() % 3 == 0) {
311  for (size_t p = 0; p < first.size() / 3; ++p) {
312  std::transform(first.cbegin(), first.cend(), second.cbegin() + (p * 3),
313  first.begin(), std::minus<precision>());
314  }
315  }
316  return first;
317  }
318 
319  template<typename precision, typename ValueT>
320  inline vector<precision>& operator-=(vector<precision>& vec, const ValueT& value)
321  {
322  static_assert(is_arithmetic<ValueT>::value, "");
323  for (auto&& elem : vec) {
324  elem -= value;
325  }
326  return vec;
327  }
328  // OPERATORS: INPLACE-MINUS
330 
332  // OPERATORS: MUL
333  template<typename precision, typename ValueT>
334  inline vector<precision> operator*(const vector<precision>& vec, const ValueT& value)
335  {
336  static_assert(is_arithmetic<ValueT>::value, "");
337  vector<precision> dest(vec);
338  dest *= value;
339  return dest;
340  }
341 
342  template<typename precision, typename ValueT>
343  inline vector<precision> operator*(const ValueT& value, const vector<precision>& vec)
344  {
345  static_assert(is_arithmetic<ValueT>::value, "");
346  ML_LOG(WARNING, "Commutativity of multiplication primaly implemented other way round."
347  << " You should switch to avoid unneccessary function calls.");
348  return vec * value;
349  }
350 
351  template<typename precision>
352  inline vector<precision> operator* (const vector<precision>& vec, const vector<precision>& values)
353  {
354  assert(vec.size() % 3 == 0 && vec.size() / 3 == values.size());
355  vector<precision> dest(vec.size(), precision(0.0));
356  for (size_t p = 0; p < values.size(); ++p) {
357  std::transform(vec.cbegin() + (p * 3), vec.cbegin() + ((p+1) * 3), dest.begin() + (p * 3),
358  [&](const precision& v) { return v * values[p]; });
359  }
360  return dest;
361  }
362  // OPERATORS: MUL
364 
366  // OPERATORS: INPLACE-MUL
367  template<typename precision, typename ValueT>
368  inline vector<precision>& operator*=(vector<precision>& vec, const ValueT& value)
369  {
370  static_assert(is_arithmetic<ValueT>::value, "");
371  for (auto&& elem : vec) {
372  elem *= value;
373  }
374  return vec;
375  }
376  // OPERATORS: INPLACE-MUL
378 
380  // OPERATORS: DIV
381  template<typename precision, typename ValueT>
382  inline vector<precision> operator/(const vector<precision>& vec, const ValueT& value)
383  {
384  static_assert(is_arithmetic<ValueT>::value, "");
385  vector<precision> dest(vec);
386  dest /= value;
387  return dest;
388  }
389 
390  template<typename precision>
391  inline vector<precision> operator/ (const vector<precision>& vec, const vector<precision>& values)
392  {
393  assert(vec.size() % 3 == 0 && vec.size() / 3 == values.size());
394  vector<precision> dest(vec.size(), precision(0.0));
395  for (size_t p = 0; p < values.size(); ++p) {
396  std::transform(vec.cbegin() + (p * 3), vec.cbegin() + ((p+1) * 3), dest.begin() + (p * 3),
397  [&](const precision& v) { return v / values[p]; });
398  }
399  return dest;
400  }
401  // OPERATORS: DIV
403 
405  // OPERATORS: INPLACE-DIV
406  template<typename precision, typename ValueT>
407  inline vector<precision>& operator/=(vector<precision>& vec, const ValueT& value)
408  {
409  static_assert(is_arithmetic<ValueT>::value, "");
410  for (auto&& elem : vec) {
411  elem /= value;
412  }
413  return vec;
414  }
415  // OPERATORS: INPLACE-DIV
417  } // ::pfasst::examples::boris
418  } // ::pfasst::examples
419 } // ::pfasst
static void zero(shared_ptr< vector< precision >> &data)
tuple data
Definition: plot.py:7
static precision norm0(typename vector< precision >::const_iterator __first, typename vector< precision >::const_iterator __second)
static precision max(const vector< precision > &data)
vector< precision > & operator-=(vector< precision > &first, const vector< precision > &second)
STL namespace.
static vector< precision > cloud_component_factory(const size_t num_particles, const size_t dim)
vector< precision > & operator*=(vector< precision > &vec, const ValueT &value)
static vector< precision > cmp_wise_div(const vector< precision > &first, const vector< precision > &second)
vector< precision > operator*(const vector< precision > &vec, const ValueT &value)
vector< precision > operator+(const vector< precision > &first, const vector< precision > &second)
static precision norm_sq(typename vector< precision >::const_iterator __first, typename vector< precision >::const_iterator __second)
#define ML_LOG(level, x)
same as LOG(level, x) from easylogging++
Definition: logging.hpp:110
vector< precision > & operator+=(vector< precision > &first, const vector< precision > &second)
static vector< precision > cmp_wise_mul(const vector< precision > &first, const vector< precision > &second)
vector< precision > operator/(const vector< precision > &vec, const ValueT &value)
static vector< precision > cross_prod_npart(const vector< precision > &first, const vector< precision > &second)
static vector< precision > norm_sq_npart(const vector< precision > &data, const size_t npart)
static vector< precision > norm0_npart(const vector< precision > &data, const size_t npart)
vector< precision > operator-(const vector< precision > &first, const vector< precision > &second)
static vector< precision > cross_prod(const vector< precision > &first, const vector< precision > &second)
vector< precision > & operator/=(vector< precision > &vec, const ValueT &value)
static precision max_abs(const vector< precision > &data)
static vector< precision > kronecker(const vector< precision > &first, const vector< precision > &second)
static void cross_prod_1part(typename vector< precision >::const_iterator __first, typename vector< precision >::const_iterator __second, typename vector< precision >::iterator __result)