OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
Dcpse.hpp
1 //
2 // Created by tommaso on 29/03/19.
3 // Modified by Abhinav and Pietro
4 #ifndef OPENFPM_PDATA_DCPSE_HPP
5 #define OPENFPM_PDATA_DCPSE_HPP
6 
7 #ifdef HAVE_EIGEN
8 
9 #include "Vector/vector_dist.hpp"
10 #include "MonomialBasis.hpp"
11 #include "DMatrix/EMatrix.hpp"
12 #include "SupportBuilder.hpp"
13 #include "Support.hpp"
14 #include "Vandermonde.hpp"
15 #include "DcpseDiagonalScalingMatrix.hpp"
16 #include "DcpseRhs.hpp"
17 
18 template<bool cond>
19 struct is_scalar {
20  template<typename op_type>
21  static auto
22  analyze(const vect_dist_key_dx &key, op_type &o1) -> typename std::remove_reference<decltype(o1.value(
23  key))>::type {
24  return o1.value(key);
25  };
26 };
27 
28 template<>
29 struct is_scalar<false> {
30  template<typename op_type>
31  static auto
32  analyze(const vect_dist_key_dx &key, op_type &o1) -> typename std::remove_reference<decltype(o1.value(
33  key))>::type {
34  return o1.value(key);
35  };
36 };
37 
38 template<unsigned int dim, typename vector_type>
39 class Dcpse {
40 public:
41 
42  typedef typename vector_type::stype T;
43  typedef typename vector_type::value_type part_type;
44  typedef vector_type vtype;
45 
46  #ifdef SE_CLASS1
47  int update_ctr=0;
48  #endif
49 
50  // This works in this way:
51  // 1) User constructs this by giving a domain of points (where one of the properties is the value of our f),
52  // the signature of the differential operator and the error order bound.
53  // 2) The machinery for assembling and solving the linear system for coefficients starts...
54  // 3) The user can then call an evaluate(point) method to get the evaluation of the differential operator
55  // on the given point.
56 private:
57  const Point<dim, unsigned int> differentialSignature;
58  const unsigned int differentialOrder;
59  const MonomialBasis<dim> monomialBasis;
60  //std::vector<EMatrix<T, Eigen::Dynamic, 1>> localCoefficients; // Each MPI rank has just access to the local ones
61  std::vector<Support> localSupports; // Each MPI rank has just access to the local ones
62  std::vector<T> localEps; // Each MPI rank has just access to the local ones
63  std::vector<T> localEpsInvPow; // Each MPI rank has just access to the local ones
64  std::vector<T> localSumA;
65 
66  openfpm::vector<size_t> kerOffsets;
67  openfpm::vector<T> calcKernels;
68 
70  double rCut;
71  unsigned int convergenceOrder;
72  double supportSizeFactor;
73 
74  support_options opt;
75 
76 public:
77 #ifdef SE_CLASS1
78  int getUpdateCtr() const
79  {
80  return update_ctr;
81  }
82 #endif
83 
84  // Here we require the first element of the aggregate to be:
85  // 1) the value of the function f on the point
86  Dcpse(vector_type &particles,
87  Point<dim, unsigned int> differentialSignature,
88  unsigned int convergenceOrder,
89  T rCut,
90  T supportSizeFactor = 1, //Maybe change this to epsilon/h or h/epsilon = c 0.9. Benchmark
91  support_options opt = support_options::RADIUS)
93  differentialSignature(differentialSignature),
94  differentialOrder(Monomial<dim>(differentialSignature).order()),
95  monomialBasis(differentialSignature.asArray(), convergenceOrder),
96  opt(opt)
97  {
98  // This
100  if (supportSizeFactor < 1)
101  {
102  initializeAdaptive(particles, convergenceOrder, rCut);
103  }
104  else
105  {
106  initializeStaticSize(particles, convergenceOrder, rCut, supportSizeFactor);
107  }
108  }
109 
110 
111 
112  template<unsigned int prp>
113  void DrawKernel(vector_type &particles, int k)
114  {
115  Support support = localSupports[k];
116  size_t xpK = k;
117  size_t kerOff = kerOffsets.get(k);
118  auto & keys = support.getKeys();
119  for (int i = 0 ; i < keys.size() ; i++)
120  {
121  size_t xqK = keys[i];
122  particles.template getProp<prp>(xqK) += calcKernels.get(kerOff+i);
123  }
124  }
125 
126  template<unsigned int prp>
127  void DrawKernelNN(vector_type &particles, int k)
128  {
129  Support support = localSupports[k];
130  size_t xpK = k;
131  size_t kerOff = kerOffsets.get(k);
132  auto & keys = support.getKeys();
133  for (int i = 0 ; i < keys.size() ; i++)
134  {
135  size_t xqK = keys[i];
136  particles.template getProp<prp>(xqK) = 1.0;
137  }
138  }
139 
140  template<unsigned int prp>
141  void DrawKernel(vector_type &particles, int k, int i)
142  {
143  Support support = localSupports[k];
144  size_t xpK = k;
145  size_t kerOff = kerOffsets.get(k);
146  auto & keys = support.getKeys();
147  for (int i = 0 ; i < keys.size() ; i++)
148  {
149  size_t xqK = keys[i];
150  particles.template getProp<prp>(xqK)[i] += calcKernels.get(kerOff+i);
151  }
152  }
153 
154  void checkMomenta(vector_type &particles)
155  {
158 
159  momenta.resize(monomialBasis.size());
160  momenta_accu.resize(monomialBasis.size());
161 
162  for (int i = 0 ; i < momenta.size() ; i++)
163  {
164  momenta.template get<0>(i) = 3000000000.0;
165  momenta.template get<1>(i) = -3000000000.0;
166  }
167 
168  auto it = particles.getDomainIterator();
169  auto supportsIt = localSupports.begin();
170  auto epsIt = localEps.begin();
171  while (it.isNext())
172  {
173  double eps = *epsIt;
174 
175  for (int i = 0 ; i < momenta.size() ; i++)
176  {
177  momenta_accu.template get<0>(i) = 0.0;
178  }
179 
180  Support support = *supportsIt;
181  size_t xpK = support.getReferencePointKey();
182  Point<dim, T> xp = particles.getPos(support.getReferencePointKey());
183  size_t kerOff = kerOffsets.get(xpK);
184  auto & keys = support.getKeys();
185  for (int i = 0 ; i < keys.size() ; i++)
186  {
187  size_t xqK = keys[i];
189  Point<dim, T> normalizedArg = (xp - xq) / eps;
190 
191  auto ker = calcKernels.get(kerOff+i);
192 
193  int counter = 0;
194  for (const Monomial<dim> &m : monomialBasis.getElements())
195  {
196  T mbValue = m.evaluate(normalizedArg);
197 
198 
199  momenta_accu.template get<0>(counter) += mbValue * ker;
200 
201  ++counter;
202  }
203 
204  }
205 
206  for (int i = 0 ; i < momenta.size() ; i++)
207  {
208  if (momenta_accu.template get<0>(i) < momenta.template get<0>(i))
209  {
210  momenta.template get<0>(i) = momenta_accu.template get<0>(i);
211  }
212 
213  if (momenta_accu.template get<1>(i) > momenta.template get<1>(i))
214  {
215  momenta.template get<1>(i) = momenta_accu.template get<0>(i);
216  }
217  }
218 
219  //
220  ++it;
221  ++supportsIt;
222  ++epsIt;
223  }
224 
225  for (int i = 0 ; i < momenta.size() ; i++)
226  {
227  std::cout << "MOMENTA: " << monomialBasis.getElements()[i] << "Min: " << momenta.template get<0>(i) << " " << "Max: " << momenta.template get<1>(i) << std::endl;
228  }
229  }
230 
239  template<unsigned int fValuePos, unsigned int DfValuePos>
240  void computeDifferentialOperator(vector_type &particles) {
241  char sign = 1;
242  if (differentialOrder % 2 == 0) {
243  sign = -1;
244  }
245 
246  auto it = particles.getDomainIterator();
247  auto supportsIt = localSupports.begin();
248  auto epsItInvPow = localEpsInvPow.begin();
249  while (it.isNext()) {
250  double epsInvPow = *epsItInvPow;
251 
252  T Dfxp = 0;
253  Support support = *supportsIt;
254  size_t xpK = support.getReferencePointKey();
255  Point<dim, typename vector_type::stype> xp = particles.getPos(support.getReferencePointKey());
256  T fxp = sign * particles.template getProp<fValuePos>(xpK);
257  size_t kerOff = kerOffsets.get(xpK);
258  auto & keys = support.getKeys();
259  for (int i = 0 ; i < keys.size() ; i++)
260  {
261  size_t xqK = keys[i];
262  T fxq = particles.template getProp<fValuePos>(xqK);
263 
264  Dfxp += (fxq + fxp) * calcKernels.get(kerOff+i);
265  }
266  Dfxp *= epsInvPow;
267  //
268  //T trueDfxp = particles.template getProp<2>(xpK);
269  // Store Dfxp in the right position
270  particles.template getProp<DfValuePos>(xpK) = Dfxp;
271  //
272  ++it;
273  ++supportsIt;
274  ++epsItInvPow;
275  }
276  }
277 
278 
284  inline int getNumNN(const vect_dist_key_dx &key)
285  {
286  return localSupports[key.getKey()].size();
287  }
288 
297  inline T getCoeffNN(const vect_dist_key_dx &key, int j)
298  {
299  size_t base = kerOffsets.get(key.getKey());
300  return calcKernels.get(base + j);
301  }
302 
308  inline size_t getIndexNN(const vect_dist_key_dx &key, int j)
309  {
310  return localSupports[key.getKey()].getKeys()[j];
311  }
312 
313 
314  inline T getSign()
315  {
316  T sign = 1.0;
317  if (differentialOrder % 2 == 0) {
318  sign = -1;
319  }
320 
321  return sign;
322  }
323 
324  T getEpsilonInvPrefactor(const vect_dist_key_dx &key)
325  {
326  return localEpsInvPow[key.getKey()];
327  }
328 
337  template<typename op_type>
338  auto computeDifferentialOperator(const vect_dist_key_dx &key,
339  op_type &o1) -> decltype(is_scalar<std::is_fundamental<decltype(o1.value(
340  key))>::value>::analyze(key, o1)) {
341 
342  typedef decltype(is_scalar<std::is_fundamental<decltype(o1.value(key))>::value>::analyze(key, o1)) expr_type;
343 
344  T sign = 1.0;
345  if (differentialOrder % 2 == 0) {
346  sign = -1;
347  }
348 
349  double eps = localEps[key.getKey()];
350  double epsInvPow = localEpsInvPow[key.getKey()];
351 
352  auto &particles = o1.getVector();
353 
354 #ifdef SE_CLASS1
355  if(particles.getMapCtr()!=this->getUpdateCtr())
356  {
357  std::cerr<<__FILE__<<":"<<__LINE__<<" Error: You forgot a DCPSE operator update after map."<<std::endl;
358  }
359 #endif
360 
361  expr_type Dfxp = 0;
362  Support support = localSupports[key.getKey()];
363  size_t xpK = support.getReferencePointKey();
364  Point<dim, T> xp = particles.getPos(xpK);
365  expr_type fxp = sign * o1.value(key);
366  size_t kerOff = kerOffsets.get(xpK);
367  auto & keys = support.getKeys();
368  for (int i = 0 ; i < keys.size() ; i++)
369  {
370  size_t xqK = keys[i];
371  expr_type fxq = o1.value(vect_dist_key_dx(xqK));
372  Dfxp = Dfxp + (fxq + fxp) * calcKernels.get(kerOff+i);
373  }
374  Dfxp = Dfxp * epsInvPow;
375  //
376  //T trueDfxp = particles.template getProp<2>(xpK);
377  // Store Dfxp in the right position
378  return Dfxp;
379  }
380 
390  template<typename op_type>
391  auto computeDifferentialOperator(const vect_dist_key_dx &key,
392  op_type &o1,
393  int i) -> typename decltype(is_scalar<std::is_fundamental<decltype(o1.value(
394  key))>::value>::analyze(key, o1))::coord_type {
395 
396  typedef typename decltype(is_scalar<std::is_fundamental<decltype(o1.value(key))>::value>::analyze(key, o1))::coord_type expr_type;
397 
398  //typedef typename decltype(o1.value(key))::blabla blabla;
399 
400  T sign = 1.0;
401  if (differentialOrder % 2 == 0) {
402  sign = -1;
403  }
404 
405  double eps = localEps[key.getKey()];
406  double epsInvPow = localEpsInvPow[key.getKey()];
407 
408  auto &particles = o1.getVector();
409 
410 #ifdef SE_CLASS1
411  if(particles.getMapCtr()!=this->getUpdateCtr())
412  {
413  std::cerr<<__FILE__<<":"<<__LINE__<<" Error: You forgot a DCPSE operator update after map."<<std::endl;
414  }
415 #endif
416 
417  expr_type Dfxp = 0;
418  Support support = localSupports[key.getKey()];
419  size_t xpK = support.getReferencePointKey();
420  Point<dim, T> xp = particles.getPos(xpK);
421  expr_type fxp = sign * o1.value(key)[i];
422  size_t kerOff = kerOffsets.get(xpK);
423  auto & keys = support.getKeys();
424  for (int j = 0 ; j < keys.size() ; j++)
425  {
426  size_t xqK = keys[j];
427  expr_type fxq = o1.value(vect_dist_key_dx(xqK))[i];
428  Dfxp = Dfxp + (fxq + fxp) * calcKernels.get(kerOff+j);
429  }
430  Dfxp = Dfxp * epsInvPow;
431  //
432  //T trueDfxp = particles.template getProp<2>(xpK);
433  // Store Dfxp in the right position
434  return Dfxp;
435  }
436 
437  void initializeUpdate(vector_type &particles)
438  {
439 #ifdef SE_CLASS1
440  update_ctr=particles.getMapCtr();
441 #endif
442 
443  localSupports.clear();
444  localSupports.resize(particles.size_local_orig());
445  localEps.clear();
446  localEps.resize(particles.size_local_orig());
447  localEpsInvPow.clear();
448  localEpsInvPow.resize(particles.size_local_orig());
449  calcKernels.clear();
450  kerOffsets.clear();
451  kerOffsets.resize(particles.size_local_orig());
452  kerOffsets.fill(-1);
453 
454  SupportBuilder<vector_type> supportBuilder(particles, differentialSignature, rCut);
455  unsigned int requiredSupportSize = monomialBasis.size() * supportSizeFactor;
456 
457  auto it = particles.getDomainIterator();
458  while (it.isNext()) {
459  // Get the points in the support of the DCPSE kernel and store the support for reuse
460  //Support<vector_type> support = supportBuilder.getSupport(it, requiredSupportSize,opt);
461  Support support = supportBuilder.getSupport(it, requiredSupportSize,opt);
462  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
463 
464  auto key_o = particles.getOriginKey(it.get());
465 
466  // Vandermonde matrix computation
468  vandermonde(support, monomialBasis,particles);
469  vandermonde.getMatrix(V);
470 
471  T eps = vandermonde.getEps();
472 
473  localSupports[key_o.getKey()] = support;
474  localEps[key_o.getKey()] = eps;
475  localEpsInvPow[key_o.getKey()] = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
476  // Compute the diagonal matrix E
477  DcpseDiagonalScalingMatrix<dim> diagonalScalingMatrix(monomialBasis);
478  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
479  diagonalScalingMatrix.buildMatrix(E, support, eps, particles);
480  // Compute intermediate matrix B
481  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
482  // Compute matrix A
483  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
484 
485  // Compute RHS vector b
486  DcpseRhs<dim> rhs(monomialBasis, differentialSignature);
487  EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
488  rhs.template getVector<T>(b);
489  // Get the vector where to store the coefficients...
490  EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
491  // ...solve the linear system...
492  a = A.colPivHouseholderQr().solve(b);
493  // ...and store the solution for later reuse
494  kerOffsets.get(key_o.getKey()) = calcKernels.size();
495 
496  Point<dim, T> xp = particles.getPosOrig(key_o);
497 
498  for (auto &xqK : support.getKeys())
499  {
501  Point<dim, T> normalizedArg = (xp - xq) / eps;
502 
503  calcKernels.add(computeKernel(normalizedArg, a));
504  }
505  //
506  ++it;
507  }
508  }
509 
510 private:
511 
512  void initializeAdaptive(vector_type &particles,
513  unsigned int convergenceOrder,
514  T rCut) {
516  supportBuilder(particles, differentialSignature, rCut);
517  unsigned int requiredSupportSize = monomialBasis.size();
518 
519  localSupports.resize(particles.size_local_orig());
520  localEps.resize(particles.size_local_orig());
521  localEpsInvPow.resize(particles.size_local_orig());
522  kerOffsets.resize(particles.size_local_orig());
523  kerOffsets.fill(-1);
524 
525  auto it = particles.getDomainIterator();
526  while (it.isNext()) {
527  const T condVTOL = 1e2;
528 
529  // Get the points in the support of the DCPSE kernel and store the support for reuse
530  Support support = supportBuilder.getSupport(it, requiredSupportSize,opt);
531  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
532 
533  // Vandermonde matrix computation
535  vandermonde(support, monomialBasis, particles);
536  vandermonde.getMatrix(V);
537 
538  T condV = conditionNumber(V, condVTOL);
539  T eps = vandermonde.getEps();
540 
541  if (condV > condVTOL) {
542  requiredSupportSize *= 2;
543  std::cout
544  << "INFO: Increasing, requiredSupportSize = " << requiredSupportSize
545  << std::endl; // debug
546  continue;
547  } else {
548  requiredSupportSize = monomialBasis.size();
549  }
550 
551  auto key_o = particles.getOriginKey(it.get());
552  localSupports[key_o.getKey()] = support;
553  localEps[key_o.getKey()] = eps;
554  localEpsInvPow[key_o.getKey()] = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
555  // Compute the diagonal matrix E
556  DcpseDiagonalScalingMatrix<dim> diagonalScalingMatrix(monomialBasis);
557  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
558  diagonalScalingMatrix.buildMatrix(E, support, eps,particles);
559  // Compute intermediate matrix B
560  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
561  // Compute matrix A
562  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
563  // Compute RHS vector b
564  DcpseRhs<dim> rhs(monomialBasis, differentialSignature);
565  EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
566  rhs.template getVector<T>(b);
567  // Get the vector where to store the coefficients...
568  EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
569  // ...solve the linear system...
570  a = A.colPivHouseholderQr().solve(b);
571  // ...and store the solution for later reuse
572  kerOffsets.get(key_o.getKey()) = calcKernels.size();
573 
574  Point<dim, T> xp = particles.getPosOrig(key_o);
575 
576  for (auto &xqK : support.getKeys())
577  {
579  Point<dim, T> normalizedArg = (xp - xq) / eps;
580 
581  calcKernels.add(computeKernel(normalizedArg, a));
582  }
583  //
584  ++it;
585  }
586  }
587 
588 
589  void initializeStaticSize(vector_type &particles,
590  unsigned int convergenceOrder,
591  T rCut,
592  T supportSizeFactor) {
593 #ifdef SE_CLASS1
594  this->update_ctr=particles.getMapCtr();
595 #endif
596  this->rCut=rCut;
597  this->supportSizeFactor=supportSizeFactor;
598  this->convergenceOrder=convergenceOrder;
600  supportBuilder(particles, differentialSignature, rCut);
601  unsigned int requiredSupportSize = monomialBasis.size() * supportSizeFactor;
602 
603  localSupports.resize(particles.size_local_orig());
604  localEps.resize(particles.size_local_orig());
605  localEpsInvPow.resize(particles.size_local_orig());
606  kerOffsets.resize(particles.size_local_orig());
607 
608  auto it = particles.getDomainIterator();
609  while (it.isNext()) {
610  // Get the points in the support of the DCPSE kernel and store the support for reuse
611  Support support = supportBuilder.getSupport(it, requiredSupportSize,opt);
612  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> V(support.size(), monomialBasis.size());
613 
614  auto key_o = particles.getOriginKey(it.get());
615 
616  // Vandermonde matrix computation
618  vandermonde(support, monomialBasis,particles);
619  vandermonde.getMatrix(V);
620 
621  T eps = vandermonde.getEps();
622 
623  localSupports[key_o.getKey()] = support;
624  localEps[key_o.getKey()] = eps;
625  localEpsInvPow[key_o.getKey()] = 1.0 / openfpm::math::intpowlog(eps,differentialOrder);
626  // Compute the diagonal matrix E
627  DcpseDiagonalScalingMatrix<dim> diagonalScalingMatrix(monomialBasis);
628  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> E(support.size(), support.size());
629  diagonalScalingMatrix.buildMatrix(E, support, eps, particles);
630  // Compute intermediate matrix B
631  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> B = E * V;
632  // Compute matrix A
633  EMatrix<T, Eigen::Dynamic, Eigen::Dynamic> A = B.transpose() * B;
634 
635  // Compute RHS vector b
636  DcpseRhs<dim> rhs(monomialBasis, differentialSignature);
637  EMatrix<T, Eigen::Dynamic, 1> b(monomialBasis.size(), 1);
638  rhs.template getVector<T>(b);
639  // Get the vector where to store the coefficients...
640  EMatrix<T, Eigen::Dynamic, 1> a(monomialBasis.size(), 1);
641  // ...solve the linear system...
642  a = A.colPivHouseholderQr().solve(b);
643  // ...and store the solution for later reuse
644  kerOffsets.get(key_o.getKey()) = calcKernels.size();
645 
646  Point<dim, T> xp = particles.getPosOrig(key_o);
647 
648  for (auto &xqK : support.getKeys())
649  {
651  Point<dim, T> normalizedArg = (xp - xq) / eps;
652 
653  calcKernels.add(computeKernel(normalizedArg, a));
654  }
655  //
656  ++it;
657  }
658  }
659 
660 
661 
662 
663  T computeKernel(Point<dim, T> x, EMatrix<T, Eigen::Dynamic, 1> & a) const {
664  T res = 0;
665  unsigned int counter = 0;
666  T expFactor = exp(-norm2(x));
667  for (const Monomial<dim> &m : monomialBasis.getElements()) {
668  T coeff = a(counter);
669  T mbValue = m.evaluate(x);
670  res += coeff * mbValue * expFactor;
671  ++counter;
672  }
673  return res;
674  }
675 
676 
677  T conditionNumber(const EMatrix<T, -1, -1> &V, T condTOL) const {
678  Eigen::JacobiSVD<Eigen::Matrix<T, Eigen::Dynamic, Eigen::Dynamic>> svd(V);
679  T cond = svd.singularValues()(0)
680  / svd.singularValues()(svd.singularValues().size() - 1);
681  if (cond > condTOL) {
682  std::cout
683  << "WARNING: cond(V) = " << cond
684  << " is greater than TOL = " << condTOL
685  << ", numPoints(V) = " << V.rows()
686  << std::endl; // debug
687  }
688  return cond;
689  }
690 
691 };
692 
693 
694 #endif
695 #endif //OPENFPM_PDATA_DCPSE_HPP
696 
auto getPosOrig(vect_dist_key_dx vec_key) const -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
St stype
space type
auto getPos(vect_dist_key_dx vec_key) -> decltype(v_pos.template get< 0 >(vec_key.getKey()))
Get the position of an element.
Grid key for a distributed grid.
size_t size()
Stub size.
Definition: map_vector.hpp:211
prop value_type
property object
__device__ __host__ size_t getKey() const
Get the key.
Distributed vector.
vector_dist_iterator getDomainIterator() const
Get an iterator that traverse the particles in the domain.
void clear()
remove all the elements
size_t size_local_orig() const
return the local size of the vector
void ghost_get_subset()
Stub does not do anything.