OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
SIndex.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  * This program was prepared by PSI.
7  * All rights in the program are reserved by PSI.
8  * Neither PSI nor the author(s)
9  * makes any warranty, express or implied, or assumes any liability or
10  * responsibility for the use of this software
11  *
12  * Visit www.amas.web.psi for more details
13  *
14  ***************************************************************************/
15 
16 // -*- C++ -*-
17 /***************************************************************************
18  *
19  * The IPPL Framework
20  *
21  *
22  * Visit http://people.web.psi.ch/adelmann/ for more details
23  *
24  ***************************************************************************/
25 
26 // include files
27 #include "Index/SIndex.h"
28 #include "Index/IndexedSIndex.h"
30 #include "Utility/PAssert.h"
31 
32 
33 
34 
36 // default constructor: this requires the user to call 'initialize'
37 // before any other actions are carried out with this SIndex
38 template<unsigned int Dim>
39 SIndex<Dim>::SIndex() : Layout(0) {
40 
41 }
42 
43 
45 // constructor: requires a FieldLayout, and optionally an offset amount
46 template<unsigned int Dim>
48 
49 
50 
51  setup();
52 }
53 
54 
56 // copy constructor
57 template<unsigned int Dim>
59  : Layout(si.Layout), Offset(si.Offset), IndexList(si.IndexList),
61 {
62 
63 
64 
65  // check in as a user of this Layout
66  Layout->checkin(*this);
67 }
68 
69 
71 // a special constructor, taking another SIndex and an Offset. This
72 // version is almost like a copy constructor, except that the given Offset
73 // is added to our own offset.
74 template<unsigned int Dim>
76  : Layout(si.Layout), Offset(si.Offset), IndexList(si.IndexList),
78 {
79 
80 
81 
82  // add in the extra offset amount
83  Offset += so;
84 
85  // check in as a user of this Layout
86  Layout->checkin(*this);
87 }
88 
89 
91 // a special constructor, taking another SIndex and an int * offset. This
92 // version is almost like a copy constructor, except that the given Offset
93 // is added to our own offset.
94 template<unsigned int Dim>
95 SIndex<Dim>::SIndex(const SIndex<Dim>& si, const int *so)
96  : Layout(si.Layout), Offset(si.Offset), IndexList(si.IndexList),
98 {
99 
100 
101 
102  // add in the extra offset amount
103  Offset += so;
104 
105  // check in as a user of this Layout
106  Layout->checkin(*this);
107 }
108 
109 
111 // destructor: frees memory used to store indices, and check out from Layout
112 template<unsigned int Dim>
114 
115  if (Layout != 0)
116  Layout->checkout(*this);
117 }
118 
119 
121 // initialize the object, if we were constructed with the default
122 // constructor
123 template<unsigned int Dim>
125 
126 
127 
128  Layout = &fl;
129  setup();
130 }
131 
132 
134 // set up our internal data structures from the constructor. Assumes
135 // the Layout and Offset have been set.
136 template<unsigned int Dim>
138 
139 
140  // check in as a user of the FieldLayout
141  Layout->checkin(*this);
142 
143  // get the number of vnodes, and make sure we have storage for them
144  IndexList.reserve(Layout->size_iv());
145 
146  // create new LSIndex objects for the local vnodes
147  typename FieldLayout<Dim>::iterator_iv locvn = Layout->begin_iv();
148  for ( ; locvn != Layout->end_iv(); ++locvn)
149  IndexList.push_back(std::make_shared<LSIndex<Dim>>((*locvn).second.get()));
150 
151  // save our bounding box information
152  BoundingBox = Layout->getDomain();
153 }
154 
155 
157 // add a new index point, specified as an Offset or as a single-point NDIndex.
158 // return success (this can fail if the point is outsize the field's domain)
159 template<unsigned int Dim>
161 
162 
163 
164  // right now, this is straightforward: try to add to each LSIndex in
165  // succession until one actually works
166  for (iterator_iv curr = begin_iv(); curr != end_iv(); ++curr) {
167  if (addIndex(curr, so)) {
168  return true;
169  }
170  }
171 
172  // if we're here, we could not find a vnode to take this point
173  return false;
174 }
175 
176 
178 // add a new index point, specified as an Offset or as a single-point NDIndex.
179 // This version specifically tells which LField to use.
180 // return success (this can fail if the point is outsize the field's domain)
181 template<unsigned int Dim>
183  const SOffset<Dim>& so) {
184 
185 
186 
187  // if the point is in the LField's region, add it
188  if ((*curr)->contains(so) && ! (*curr)->hasIndex(so)) {
189  (*curr)->addIndex(so);
190  return true;
191  }
192 
193  // if we're here, the point was outside the given LField's domain
194  return false;
195 }
196 
197 
199 // same as above, but taking an NDIndex. One point is added to our lists
200 // for each point in the NDIndex region (e.g., if a 2x3 NDIndex is given,
201 // 6 points in total will be added to this SIndex).
202 template<unsigned int Dim>
203 void SIndex<Dim>::addIndex(const NDIndex<Dim>& constndi) {
204 
205 
206 
207  // cast away const; we are not modifying the NDIndex, so this should be ok
208  NDIndex<Dim>& ndi((NDIndex<Dim> &)constndi);
209 
210  // calculate the total number of points, and counters for looping
211  unsigned int d, totalnum = ndi.size();
212  Index::iterator counter[Dim];
213  for (d=0; d < Dim; ++d)
214  counter[d] = ndi[d].begin();
215 
216  while (totalnum-- > 0) {
217  // create an SOffset obj and add it to our lists
218  SOffset<Dim> newpoint;
219  for (d=0; d < Dim; ++d)
220  newpoint[d] = *(counter[d]);
221  addIndex(newpoint);
222 
223  // increment the index iterators
224  unsigned int chkdim = 0;
225  while(chkdim < Dim) {
226  ++(counter[chkdim]);
227  if (counter[chkdim] == ndi[chkdim].end()) {
228  counter[chkdim] = ndi[chkdim].begin();
229  chkdim++;
230  } else {
231  break;
232  }
233  }
234  }
235 }
236 
237 
239 // add a new index point, specified as an Offset or as a single-point NDIndex.
240 // return success (this can fail if the point is outsize the field's domain)
241 template<unsigned int Dim>
243 
244 
245 
246  // right now, this is straightforward: try to add to each LSIndex in
247  // succession until one actually works
248  for (iterator_iv curr = begin_iv(); curr != end_iv(); ++curr)
249  if (removeIndex(curr, so))
250  return true;
251 
252  // if we're here, we could not find a vnode to take this point
253  return false;
254 }
255 
256 
258 // add a new index point, specified as an Offset or as a single-point NDIndex.
259 // This version specifically tells which LField to use.
260 // return success (this can fail if the point is outsize the field's domain)
261 template<unsigned int Dim>
263  const SOffset<Dim>& so) {
264 
265 
266  if ((*curr)->hasIndex(so)) {
267  (*curr)->removeIndex(so);
268  return true;
269  }
270  return false;
271 }
272 
273 
275 // same as above, but taking an NDIndex. One point is added to our lists
276 // for each point in the NDIndex region (e.g., if a 2x3 NDIndex is given,
277 // 6 points in total will be added to this SIndex).
278 template<unsigned int Dim>
279 void SIndex<Dim>::removeIndex(const NDIndex<Dim>& constndi) {
280 
281 
282 
283  // cast away const; we are not modifying the NDIndex, so this should be ok
284  NDIndex<Dim>& ndi((NDIndex<Dim> &)constndi);
285 
286  // calculate the total number of points, and counters for looping
287  unsigned int d, totalnum = ndi.size();
288  Index::iterator counter[Dim];
289  for (d=0; d < Dim; ++d)
290  counter[d] = ndi[d].begin();
291 
292  while (totalnum-- > 0) {
293  // create an SOffset obj and add it to our lists
294  SOffset<Dim> newpoint;
295  for (d=0; d < Dim; ++d)
296  newpoint[d] = *(counter[d]);
297  removeIndex(newpoint);
298 
299  // increment the index iterators
300  unsigned int chkdim = 0;
301  while(chkdim < Dim) {
302  ++(counter[chkdim]);
303  if (counter[chkdim] == ndi[chkdim].end()) {
304  counter[chkdim] = ndi[chkdim].begin();
305  chkdim++;
306  } else {
307  break;
308  }
309  }
310  }
311 }
312 
313 
315 // reserve storage space equal to the given fraction of the size of
316 // each vnode. if fraction=1.0, reserve storage for the entire vnode.
317 template<unsigned int Dim>
318 void SIndex<Dim>::reserve(double fraction) {
319  for (iterator_iv a = begin_iv(); a != end_iv(); ++a) {
320  typename LSIndex<Dim>::size_type newcapacity = (*a)->getDomain().size();
321  if (fraction < 0.9999 && fraction > 0.0)
322  newcapacity = static_cast<typename LSIndex<Dim>::size_type>(fraction *
323  static_cast<double>(newcapacity));
324  (*a)->reserve(newcapacity);
325  }
326 }
327 
328 
330 // clear out the existing indices
331 template<unsigned int Dim>
333 
334 
335  // tell all LSIndex objects to remove their points
336  for (iterator_iv a = begin_iv(); a != end_iv(); ++a) {
337  (*a)->clear();
338  }
339 }
340 
341 
343 // return whether the given point is contained here
344 template<unsigned int Dim>
345 bool SIndex<Dim>::hasIndex(const SOffset<Dim>& so) const {
346 
347 
348 
349  for (const_iterator_iv a = begin_iv(); a != end_iv(); ++a)
350  if ((*a)->hasIndex(so))
351  return true;
352  return false;
353 }
354 
355 
357 // assignment operator
358 // NOTE: this right now only works properly when the layout's match
359 template<unsigned int Dim>
361 
362 
363 
364  if (&si != this) {
365  // copy the offset and layout, checking ourselves in if necessary
366  Offset = si.Offset;
367  if (Layout == 0 || Layout != si.Layout) {
368  if (Layout != 0)
369  Layout->checkout(*this);
370  Layout = si.Layout;
371  Layout->checkin(*this);
372  }
373 
374  // copy the list of index objects, replacing our current contents
375  IndexList = si.IndexList;
376 
377  // copy the bounding box
379  }
380 
381  return *this;
382 }
383 
384 
386 // assignment operator from a single SOffset. This will leave this SIndex
387 // with just the one point.
388 template<unsigned int Dim>
390 
391 
392 
393  // put in the single point
394  clear();
395  addIndex(so);
396 
397  // set our bounding box to just this point
398  toNDIndex(so, BoundingBox);
399 
400  return *this;
401 }
402 
403 
405 // assignment operator from an NDIndex. All the points in the index space
406 // will be added.
407 template<unsigned int Dim>
409 
410 
411 
412  // put in all the points from the NDIndex
413  clear();
414  addIndex(ndi);
415 
416  // set our bounding box to this NDIndex domain
417  BoundingBox = ndi;
418 
419  return *this;
420 }
421 
422 
424 // intersection operator, with another SIndex object.
425 // NOTE: this right now only works properly when the layout's match
426 template<unsigned int Dim>
428 
429 
430 
431  if (&si != this) {
432  // for all our own points, only keep those which are in the other one
433  SIndex<Dim> newval(*Layout);
434  const_iterator_iv a = begin_iv();
435  const_iterator_iv ea = end_iv();
436  iterator_iv na = newval.begin_iv();
437  for ( ; a != ea; ++a, ++na) {
438  typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
439  typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
440  for ( ; ls_i != ls_e ; ++ls_i) {
441  if (si.hasIndex(*ls_i))
442  newval.addIndex(na, *ls_i);
443  }
444  }
445 
446  // copy over the points to here
447  *this = newval;
448 
449  // the bounding box of the intersection will be the intersection
450  // of the two original bounding boxes
451  BoundingBox = BoundingBox.intersect(si.BoundingBox);
452  }
453 
454  return *this;
455 }
456 
457 
459 // intersection operator, with another SOffset object.
460 template<unsigned int Dim>
462 
463 
464 
465  bool found = hasIndex(so);
466  clear();
467  if (found)
468  addIndex(so);
469  toNDIndex(so, BoundingBox);
470 
471  return *this;
472 }
473 
474 
476 // intersection operator, with the points in an NDIndex
477 template<unsigned int Dim>
479 
480 
481 
482  // for all our own points, only keep those which are in the other one
483  SIndex<Dim> newval(*Layout);
484  const_iterator_iv a = begin_iv();
485  const_iterator_iv ea = end_iv();
486  iterator_iv na = newval.begin_iv();
487  for ( ; a != ea; ++a, ++na) {
488  typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
489  typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
490  for ( ; ls_i != ls_e ; ++ls_i) {
491  if ((*ls_i).inside(ndi))
492  newval.addIndex(na, *ls_i);
493  }
494  }
495 
496  // the bounding box of the intersection will be the intersection
497  // of the two original bounding boxes
498  BoundingBox = BoundingBox.intersect(ndi);
499 
500  // copy over the points to here
501  *this = newval;
502  return *this;
503 }
504 
505 
507 // union operator, with another SIndex or SOffset object. This will
508 // append the point if it is not already present.
509 // NOTE: this right now only works properly when the layout's match.
510 template<unsigned int Dim>
512 
513 
514 
515  if (&si != this) {
516  const_iterator_iv a = si.begin_iv();
517  const_iterator_iv ea = si.end_iv();
518  iterator_iv na = begin_iv();
519  for ( ; a != ea; ++a, ++na) {
520  typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
521  typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
522  for ( ; ls_i != ls_e ; ++ls_i)
523  addIndex(na, *ls_i);
524  }
525 
526  // just reset the bounding box to the original full domain
527  BoundingBox = Layout->getDomain();
528  }
529 
530  return *this;
531 }
532 
533 
535 // union operator, with another SIndex or SOffset object. This will
536 // append the point if it is not already present.
537 template<unsigned int Dim>
539 
540 
541 
542  addIndex(so);
543 
544  // just reset the bounding box to the original full domain
545  BoundingBox = Layout->getDomain();
546 
547  return *this;
548 }
549 
550 
552 // union operator, with an NDIndex object. This just needs to add the
553 // points in the NDIndex object
554 template<unsigned int Dim>
556 
557 
558 
559  addIndex(ndi);
560 
561  // just reset the bounding box to the original full domain
562  BoundingBox = Layout->getDomain();
563 
564  return *this;
565 }
566 
567 
569 // () operators which make a copy of this SIndex with an extra offset.
570 // These are functionally identical to the operator+, but provide a
571 // nicer syntax. That is, si(1,1) means si + SOffset<Dim>(1,1)
572 template<unsigned int Dim>
574 
575 
576 
577  CTAssert(Dim==1);
578  return SIndex(*this, SOffset<Dim>(i0));
579 }
580 
581 template<unsigned int Dim>
583 
584 
585  CTAssert(Dim==2);
586  return SIndex(*this, SOffset<Dim>(i0,i1));
587 }
588 
589 template<unsigned int Dim>
590 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2) {
591 
592 
593 
594  CTAssert(Dim==3);
595  return SIndex(*this, SOffset<Dim>(i0,i1,i2));
596 }
597 
598 template<unsigned int Dim>
599 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3) {
600 
601 
602 
603  CTAssert(Dim==4);
604  return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3));
605 }
606 
607 template<unsigned int Dim>
608 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3, int i4) {
609 
610 
611 
612  CTAssert(Dim==5);
613  return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3,i4));
614 }
615 
616 template<unsigned int Dim>
617 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3, int i4,
618  int i5) {
619 
620 
621 
622  CTAssert(Dim==6);
623  return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3,i4,i5));
624 }
625 
626 template<unsigned int Dim>
628 
629 
630 
631  return SIndex(*this, so);
632 }
633 
634 template<unsigned int Dim>
636 
637 
638 
639  return SIndex(*this, SOffset<Dim>(so));
640 }
641 
642 
644 // operator[], which is used with Index or NDIndex objects to further
645 // subset the data. This will only work if the dimension of the Index
646 // arguments + Brackets is <= Dim. Otherwise, too many dimensions worth
647 // of Index objects are being applied
648 template<unsigned int Dim>
650 
651 
652 
653  CTAssert(Dim >= 1);
654  NDIndex<Dim> dom;
655  dom[0] = i;
656  return IndexedSIndex<Dim,1>(*this, dom);
657 }
658 
659 
660 
662 // convert from the given SOffset value to an NDIndex, with offset added
663 template<unsigned int Dim>
665 
666 
667 
668  for (unsigned int d=0; d < Dim; ++d) {
669  int m = val[d] + Offset[d];
670  NDI[d] = Index(m, m);
671  }
672 }
673 
674 
676 // return the total size, which is the sum of the individual sizes
677 template<unsigned int Dim>
679 
680 
681 
682  size_type_iv retval = 0;
683  for (const_iterator_iv a = begin_iv(); a != end_iv(); ++a)
684  retval += (*a)->size();
685 
686  return retval;
687 }
688 
689 
691 // change to using a new layout.
692 // NOTE: this needs to be fixed to properly redistribute points to
693 // their proper nodes.
694 template<unsigned int Dim>
696 
697 
698 
699  // create a new, empty SIndex
700  SIndex<Dim> newindx(fl, Offset);
701 
702  // NOTE: PUT CODE TO REDISTRIBUTE POINTS PROPERLY HERE
703 
704 
705  // copy over this new SIndex to ourselves
706  *this = newindx;
707 }
708 
709 
711 // Repartition onto a new layout
712 template<unsigned int Dim>
714 
715 
716 
717  if (Layout != 0 && userlist->getUserListID() == Layout->get_Id()) {
718  // it is indeed our layout which is being repartitioned. The easiest
719  // way to do this is to just use the setFieldLayout with our current
720  // layout, but which we now know is partitioned differently.
721  setFieldLayout(*Layout);
722  }
723 }
724 
725 
727 // Tell this object that an object is being deleted
728 template<unsigned int Dim>
730 
731 
732 
733  if (Layout != 0 && userlist->getUserListID() == Layout->get_Id())
734  Layout = 0;
735 }
736 
737 
739 // write contents to given ostream
740 template<unsigned int Dim>
741 std::ostream& operator<<(std::ostream& o, const SIndex<Dim>& si) {
742 
743 
744 
745  o << "vnodes = " << si.size_iv();
746  o << ", offset = " << si.getOffset();
747  o << ", bounding box = " << si.getDomain();
748  o << ", points in each LField (w/offset):" << std::endl;
749  for (typename SIndex<Dim>::const_iterator_iv a=si.begin_iv(); a!=si.end_iv(); ++a) {
750  o << " In LField w/domain=" << (*a)->getDomain() << ":" << std::endl;
751  o << " compressed = " << (*a)->IsCompressed() << std::endl;
752  unsigned int lsize = (*a)->size();
753  for (unsigned int i=0; i < lsize; ++i)
754  o << " " << (*a)->getIndex(i) + si.getOffset() << std::endl;
755  }
756 
757  return o;
758 }
759 
760 
762 // print out debugging info
763 template<unsigned int Dim>
765 
766 
767  o << *this << endl;
768 }
769 
770 
771 /***************************************************************************
772  * $RCSfile: SIndex.cpp,v $ $Author: adelmann $
773  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $
774  * IPPL_VERSION_ID: $Id: SIndex.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $
775  ***************************************************************************/
ID_t getUserListID() const
Definition: UserList.cpp:54
container_t::const_iterator const_iterator_iv
Definition: SIndex.h:71
void setFieldLayout(FieldLayout< Dim > &)
Definition: SIndex.hpp:695
bool addIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:160
virtual void notifyUserOfDelete(UserList *)
Definition: SIndex.hpp:729
bool removeIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:242
#define CTAssert(c)
Definition: PAssert.h:35
IndexedSIndex< Dim, 1 > operator[](const Index &)
Definition: SIndex.hpp:649
FieldLayout< Dim > * Layout
Definition: SIndex.h:276
ac_id_vnodes::iterator iterator_iv
Definition: FieldLayout.h:73
Definition: Offset.h:53
SIndex< Dim > & operator=(const PETE_Expr< T1 > &rhs)
Definition: SIndex.h:98
void setup()
Definition: SIndex.hpp:137
container_t::iterator iterator_iv
Definition: SIndex.h:70
void reserve(double=1.0)
Definition: SIndex.hpp:318
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is and will automatically terminate your rights under this License parties who have received or from you under this License will not have their licenses terminated so long as such parties remain in full compliance You are not required to accept this since you have not signed it nothing else grants you permission to modify or distribute the Program or its derivative works These actions are prohibited by law if you do not accept this License by modifying or distributing the you indicate your acceptance of this License to do so
Definition: LICENSE:185
clearpage the user may choose between constant or variable radius This model includes fringe fields begin
Definition: multipole_t.tex:6
Definition: Index.h:236
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
container_t::const_iterator const_iterator
Definition: LSIndex.h:38
container_t::size_type size_type
Definition: LSIndex.h:39
NDIndex< Dim > BoundingBox
Definition: SIndex.h:288
void clear()
Definition: SIndex.hpp:332
void toNDIndex(const SOffset< Dim > &, NDIndex< Dim > &)
Definition: SIndex.hpp:664
void initialize(FieldLayout< Dim > &)
Definition: SIndex.hpp:124
Definition: Inform.h:42
unsigned size() const
bool hasIndex(const SOffset< Dim > &) const
Definition: SIndex.hpp:345
SIndex< Dim > operator()(int)
Definition: SIndex.hpp:573
container_t::size_type size_type_iv
Definition: SIndex.h:72
SIndex()
Definition: SIndex.hpp:39
const unsigned Dim
iterator_iv begin_iv()
Definition: SIndex.h:245
Definition: SIndex.h:27
SIndex< Dim > & operator|=(const SIndex< Dim > &)
Definition: SIndex.hpp:511
size_type_iv size() const
Definition: SIndex.hpp:678
SOffset< Dim > Offset
Definition: SIndex.h:280
SIndex< Dim > & operator&=(const SIndex< Dim > &)
Definition: SIndex.hpp:427
void printDebug(Inform &) const
Definition: SIndex.hpp:764
virtual ~SIndex()
Definition: SIndex.hpp:113
iterator_iv end_iv()
Definition: SIndex.h:246
container_t IndexList
Definition: SIndex.h:283
iterator_iv end_iv()
Definition: FieldLayout.h:716
virtual void Repartition(UserList *)
Definition: SIndex.hpp:713
end
Definition: multipole_t.tex:9