OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
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),
60  BoundingBox(si.BoundingBox)
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),
77  BoundingBox(si.BoundingBox)
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),
97  BoundingBox(si.BoundingBox)
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(new 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).CopyForWrite();
190  (*curr)->addIndex(so);
191  return true;
192  }
193 
194  // if we're here, the point was outside the given LField's domain
195  return false;
196 }
197 
198 
200 // same as above, but taking an NDIndex. One point is added to our lists
201 // for each point in the NDIndex region (e.g., if a 2x3 NDIndex is given,
202 // 6 points in total will be added to this SIndex).
203 template<unsigned int Dim>
204 void SIndex<Dim>::addIndex(const NDIndex<Dim>& constndi) {
205 
206 
207 
208  // cast away const; we are not modifying the NDIndex, so this should be ok
209  NDIndex<Dim>& ndi((NDIndex<Dim> &)constndi);
210 
211  // calculate the total number of points, and counters for looping
212  unsigned int d, totalnum = ndi.size();
213  Index::iterator counter[Dim];
214  for (d=0; d < Dim; ++d)
215  counter[d] = ndi[d].begin();
216 
217  while (totalnum-- > 0) {
218  // create an SOffset obj and add it to our lists
219  SOffset<Dim> newpoint;
220  for (d=0; d < Dim; ++d)
221  newpoint[d] = *(counter[d]);
222  addIndex(newpoint);
223 
224  // increment the index iterators
225  unsigned int chkdim = 0;
226  while(chkdim < Dim) {
227  ++(counter[chkdim]);
228  if (counter[chkdim] == ndi[chkdim].end()) {
229  counter[chkdim] = ndi[chkdim].begin();
230  chkdim++;
231  } else {
232  break;
233  }
234  }
235  }
236 }
237 
238 
240 // add a new index point, specified as an Offset or as a single-point NDIndex.
241 // return success (this can fail if the point is outsize the field's domain)
242 template<unsigned int Dim>
244 
245 
246 
247  // right now, this is straightforward: try to add to each LSIndex in
248  // succession until one actually works
249  for (iterator_iv curr = begin_iv(); curr != end_iv(); ++curr)
250  if (removeIndex(curr, so))
251  return true;
252 
253  // if we're here, we could not find a vnode to take this point
254  return false;
255 }
256 
257 
259 // add a new index point, specified as an Offset or as a single-point NDIndex.
260 // This version specifically tells which LField to use.
261 // return success (this can fail if the point is outsize the field's domain)
262 template<unsigned int Dim>
264  const SOffset<Dim>& so) {
265 
266 
267  if ((*curr)->hasIndex(so)) {
268  (*curr).CopyForWrite();
269  (*curr)->removeIndex(so);
270  return true;
271  }
272  return false;
273 }
274 
275 
277 // same as above, but taking an NDIndex. One point is added to our lists
278 // for each point in the NDIndex region (e.g., if a 2x3 NDIndex is given,
279 // 6 points in total will be added to this SIndex).
280 template<unsigned int Dim>
281 void SIndex<Dim>::removeIndex(const NDIndex<Dim>& constndi) {
282 
283 
284 
285  // cast away const; we are not modifying the NDIndex, so this should be ok
286  NDIndex<Dim>& ndi((NDIndex<Dim> &)constndi);
287 
288  // calculate the total number of points, and counters for looping
289  unsigned int d, totalnum = ndi.size();
290  Index::iterator counter[Dim];
291  for (d=0; d < Dim; ++d)
292  counter[d] = ndi[d].begin();
293 
294  while (totalnum-- > 0) {
295  // create an SOffset obj and add it to our lists
296  SOffset<Dim> newpoint;
297  for (d=0; d < Dim; ++d)
298  newpoint[d] = *(counter[d]);
299  removeIndex(newpoint);
300 
301  // increment the index iterators
302  unsigned int chkdim = 0;
303  while(chkdim < Dim) {
304  ++(counter[chkdim]);
305  if (counter[chkdim] == ndi[chkdim].end()) {
306  counter[chkdim] = ndi[chkdim].begin();
307  chkdim++;
308  } else {
309  break;
310  }
311  }
312  }
313 }
314 
315 
317 // reserve storage space equal to the given fraction of the size of
318 // each vnode. if fraction=1.0, reserve storage for the entire vnode.
319 template<unsigned int Dim>
320 void SIndex<Dim>::reserve(double fraction) {
321  for (iterator_iv a = begin_iv(); a != end_iv(); ++a) {
322  typename LSIndex<Dim>::size_type newcapacity = (*a)->getDomain().size();
323  if (fraction < 0.9999 && fraction > 0.0)
324  newcapacity = static_cast<typename LSIndex<Dim>::size_type>(fraction *
325  static_cast<double>(newcapacity));
326  (*a)->reserve(newcapacity);
327  }
328 }
329 
330 
332 // clear out the existing indices
333 template<unsigned int Dim>
335 
336 
337  // tell all LSIndex objects to remove their points
338  for (iterator_iv a = begin_iv(); a != end_iv(); ++a) {
339  (*a).CopyForWrite();
340  (*a)->clear();
341  }
342 }
343 
344 
346 // return whether the given point is contained here
347 template<unsigned int Dim>
348 bool SIndex<Dim>::hasIndex(const SOffset<Dim>& so) const {
349 
350 
351 
352  for (const_iterator_iv a = begin_iv(); a != end_iv(); ++a)
353  if ((*a)->hasIndex(so))
354  return true;
355  return false;
356 }
357 
358 
360 // assignment operator
361 // NOTE: this right now only works properly when the layout's match
362 template<unsigned int Dim>
364 
365 
366 
367  if (&si != this) {
368  // copy the offset and layout, checking ourselves in if necessary
369  Offset = si.Offset;
370  if (Layout == 0 || Layout != si.Layout) {
371  if (Layout != 0)
372  Layout->checkout(*this);
373  Layout = si.Layout;
374  Layout->checkin(*this);
375  }
376 
377  // copy the list of index objects, replacing our current contents
378  IndexList = si.IndexList;
379 
380  // copy the bounding box
381  BoundingBox = si.BoundingBox;
382  }
383 
384  return *this;
385 }
386 
387 
389 // assignment operator from a single SOffset. This will leave this SIndex
390 // with just the one point.
391 template<unsigned int Dim>
393 
394 
395 
396  // put in the single point
397  clear();
398  addIndex(so);
399 
400  // set our bounding box to just this point
401  toNDIndex(so, BoundingBox);
402 
403  return *this;
404 }
405 
406 
408 // assignment operator from an NDIndex. All the points in the index space
409 // will be added.
410 template<unsigned int Dim>
412 
413 
414 
415  // put in all the points from the NDIndex
416  clear();
417  addIndex(ndi);
418 
419  // set our bounding box to this NDIndex domain
420  BoundingBox = ndi;
421 
422  return *this;
423 }
424 
425 
427 // intersection operator, with another SIndex object.
428 // NOTE: this right now only works properly when the layout's match
429 template<unsigned int Dim>
431 
432 
433 
434  if (&si != this) {
435  // for all our own points, only keep those which are in the other one
436  SIndex<Dim> newval(*Layout);
437  const_iterator_iv a = begin_iv();
438  const_iterator_iv ea = end_iv();
439  iterator_iv na = newval.begin_iv();
440  for ( ; a != ea; ++a, ++na) {
441  typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
442  typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
443  for ( ; ls_i != ls_e ; ++ls_i) {
444  if (si.hasIndex(*ls_i))
445  newval.addIndex(na, *ls_i);
446  }
447  }
448 
449  // copy over the points to here
450  *this = newval;
451 
452  // the bounding box of the intersection will be the intersection
453  // of the two original bounding boxes
454  BoundingBox = BoundingBox.intersect(si.BoundingBox);
455  }
456 
457  return *this;
458 }
459 
460 
462 // intersection operator, with another SOffset object.
463 template<unsigned int Dim>
465 
466 
467 
468  bool found = hasIndex(so);
469  clear();
470  if (found)
471  addIndex(so);
472  toNDIndex(so, BoundingBox);
473 
474  return *this;
475 }
476 
477 
479 // intersection operator, with the points in an NDIndex
480 template<unsigned int Dim>
482 
483 
484 
485  // for all our own points, only keep those which are in the other one
486  SIndex<Dim> newval(*Layout);
487  const_iterator_iv a = begin_iv();
488  const_iterator_iv ea = end_iv();
489  iterator_iv na = newval.begin_iv();
490  for ( ; a != ea; ++a, ++na) {
491  typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
492  typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
493  for ( ; ls_i != ls_e ; ++ls_i) {
494  if ((*ls_i).inside(ndi))
495  newval.addIndex(na, *ls_i);
496  }
497  }
498 
499  // the bounding box of the intersection will be the intersection
500  // of the two original bounding boxes
501  BoundingBox = BoundingBox.intersect(ndi);
502 
503  // copy over the points to here
504  *this = newval;
505  return *this;
506 }
507 
508 
510 // union operator, with another SIndex or SOffset object. This will
511 // append the point if it is not already present.
512 // NOTE: this right now only works properly when the layout's match.
513 template<unsigned int Dim>
515 
516 
517 
518  if (&si != this) {
519  const_iterator_iv a = si.begin_iv();
520  const_iterator_iv ea = si.end_iv();
521  iterator_iv na = begin_iv();
522  for ( ; a != ea; ++a, ++na) {
523  typename LSIndex<Dim>::const_iterator ls_i = (*a)->begin();
524  typename LSIndex<Dim>::const_iterator ls_e = (*a)->end();
525  for ( ; ls_i != ls_e ; ++ls_i)
526  addIndex(na, *ls_i);
527  }
528 
529  // just reset the bounding box to the original full domain
530  BoundingBox = Layout->getDomain();
531  }
532 
533  return *this;
534 }
535 
536 
538 // union operator, with another SIndex or SOffset object. This will
539 // append the point if it is not already present.
540 template<unsigned int Dim>
542 
543 
544 
545  addIndex(so);
546 
547  // just reset the bounding box to the original full domain
548  BoundingBox = Layout->getDomain();
549 
550  return *this;
551 }
552 
553 
555 // union operator, with an NDIndex object. This just needs to add the
556 // points in the NDIndex object
557 template<unsigned int Dim>
559 
560 
561 
562  addIndex(ndi);
563 
564  // just reset the bounding box to the original full domain
565  BoundingBox = Layout->getDomain();
566 
567  return *this;
568 }
569 
570 
572 // () operators which make a copy of this SIndex with an extra offset.
573 // These are functionally identical to the operator+, but provide a
574 // nicer syntax. That is, si(1,1) means si + SOffset<Dim>(1,1)
575 template<unsigned int Dim>
577 
578 
579 
580  CTAssert(Dim==1);
581  return SIndex(*this, SOffset<Dim>(i0));
582 }
583 
584 template<unsigned int Dim>
586 
587 
588  CTAssert(Dim==2);
589  return SIndex(*this, SOffset<Dim>(i0,i1));
590 }
591 
592 template<unsigned int Dim>
593 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2) {
594 
595 
596 
597  CTAssert(Dim==3);
598  return SIndex(*this, SOffset<Dim>(i0,i1,i2));
599 }
600 
601 template<unsigned int Dim>
602 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3) {
603 
604 
605 
606  CTAssert(Dim==4);
607  return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3));
608 }
609 
610 template<unsigned int Dim>
611 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3, int i4) {
612 
613 
614 
615  CTAssert(Dim==5);
616  return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3,i4));
617 }
618 
619 template<unsigned int Dim>
620 SIndex<Dim> SIndex<Dim>::operator()(int i0, int i1, int i2, int i3, int i4,
621  int i5) {
622 
623 
624 
625  CTAssert(Dim==6);
626  return SIndex(*this, SOffset<Dim>(i0,i1,i2,i3,i4,i5));
627 }
628 
629 template<unsigned int Dim>
631 
632 
633 
634  return SIndex(*this, so);
635 }
636 
637 template<unsigned int Dim>
639 
640 
641 
642  return SIndex(*this, SOffset<Dim>(so));
643 }
644 
645 
647 // operator[], which is used with Index or NDIndex objects to further
648 // subset the data. This will only work if the dimension of the Index
649 // arguments + Brackets is <= Dim. Otherwise, too many dimensions worth
650 // of Index objects are being applied
651 template<unsigned int Dim>
653 
654 
655 
656  CTAssert(Dim >= 1);
657  NDIndex<Dim> dom;
658  dom[0] = i;
659  return IndexedSIndex<Dim,1>(*this, dom);
660 }
661 
662 
663 
665 // convert from the given SOffset value to an NDIndex, with offset added
666 template<unsigned int Dim>
668 
669 
670 
671  for (unsigned int d=0; d < Dim; ++d) {
672  int m = val[d] + Offset[d];
673  NDI[d] = Index(m, m);
674  }
675 }
676 
677 
679 // return the total size, which is the sum of the individual sizes
680 template<unsigned int Dim>
682 
683 
684 
685  size_type_iv retval = 0;
686  for (const_iterator_iv a = begin_iv(); a != end_iv(); ++a)
687  retval += (*a)->size();
688 
689  return retval;
690 }
691 
692 
694 // change to using a new layout.
695 // NOTE: this needs to be fixed to properly redistribute points to
696 // their proper nodes.
697 template<unsigned int Dim>
699 
700 
701 
702  // create a new, empty SIndex
703  SIndex<Dim> newindx(fl, Offset);
704 
705  // NOTE: PUT CODE TO REDISTRIBUTE POINTS PROPERLY HERE
706 
707 
708  // copy over this new SIndex to ourselves
709  *this = newindx;
710 }
711 
712 
714 // Repartition onto a new layout
715 template<unsigned int Dim>
717 
718 
719 
720  if (Layout != 0 && userlist->getUserListID() == Layout->get_Id()) {
721  // it is indeed our layout which is being repartitioned. The easiest
722  // way to do this is to just use the setFieldLayout with our current
723  // layout, but which we now know is partitioned differently.
724  setFieldLayout(*Layout);
725  }
726 }
727 
728 
730 // Tell this object that an object is being deleted
731 template<unsigned int Dim>
733 
734 
735 
736  if (Layout != 0 && userlist->getUserListID() == Layout->get_Id())
737  Layout = 0;
738 }
739 
740 
742 // write contents to given ostream
743 template<unsigned int Dim>
744 std::ostream& operator<<(std::ostream& o, const SIndex<Dim>& si) {
745 
746 
747 
748  o << "vnodes = " << si.size_iv();
749  o << ", offset = " << si.getOffset();
750  o << ", bounding box = " << si.getDomain();
751  o << ", points in each LField (w/offset):" << std::endl;
752  for (typename SIndex<Dim>::const_iterator_iv a=si.begin_iv(); a!=si.end_iv(); ++a) {
753  o << " In LField w/domain=" << (*a)->getDomain() << ":" << std::endl;
754  o << " compressed = " << (*a)->IsCompressed() << std::endl;
755  unsigned int lsize = (*a)->size();
756  for (unsigned int i=0; i < lsize; ++i)
757  o << " " << (*a)->getIndex(i) + si.getOffset() << std::endl;
758  }
759 
760  return o;
761 }
762 
763 
765 // print out debugging info
766 template<unsigned int Dim>
768 
769 
770  o << *this << endl;
771 }
772 
773 
774 /***************************************************************************
775  * $RCSfile: SIndex.cpp,v $ $Author: adelmann $
776  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $
777  * IPPL_VERSION_ID: $Id: SIndex.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $
778  ***************************************************************************/
void printDebug(Inform &) const
Definition: SIndex.hpp:767
Definition: Offset.h:66
void toNDIndex(const SOffset< Dim > &, NDIndex< Dim > &)
Definition: SIndex.hpp:667
Definition: SIndex.h:28
void reserve(double=1.0)
Definition: SIndex.hpp:320
ID_t getUserListID() const
Definition: UserList.cpp:54
void setFieldLayout(FieldLayout< Dim > &)
Definition: SIndex.hpp:698
container_t::const_iterator const_iterator
Definition: LSIndex.h:39
unsigned size() const
#define CTAssert(c)
Definition: PAssert.h:40
virtual void notifyUserOfDelete(UserList *)
Definition: SIndex.hpp:732
container_t::const_iterator const_iterator_iv
Definition: SIndex.h:72
virtual ~SIndex()
Definition: SIndex.hpp:113
bool addIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:160
FieldLayout< Dim > * Layout
Definition: SIndex.h:277
bool removeIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:243
SOffset< Dim > Offset
Definition: SIndex.h:281
SIndex()
Definition: SIndex.hpp:39
iterator_iv begin_iv()
Definition: SIndex.h:246
SIndex< Dim > & operator=(const PETE_Expr< T1 > &rhs)
Definition: SIndex.h:99
Definition: Index.h:236
iterator_iv end_iv()
Definition: FieldLayout.h:716
container_t::iterator iterator_iv
Definition: SIndex.h:71
ac_id_vnodes::iterator iterator_iv
Definition: FieldLayout.h:73
void clear()
Definition: SIndex.hpp:334
bool hasIndex(const SOffset< Dim > &) const
Definition: SIndex.hpp:348
SIndex< Dim > & operator&=(const SIndex< Dim > &)
Definition: SIndex.hpp:430
SIndex< Dim > operator()(int)
Definition: SIndex.hpp:576
iterator_iv end_iv()
Definition: SIndex.h:247
void initialize(FieldLayout< Dim > &)
Definition: SIndex.hpp:124
IndexedSIndex< Dim, 1 > operator[](const Index &)
Definition: SIndex.hpp:652
SIndex< Dim > & operator|=(const SIndex< Dim > &)
Definition: SIndex.hpp:514
container_t::size_type size_type
Definition: LSIndex.h:40
virtual void Repartition(UserList *)
Definition: SIndex.hpp:716
size_type_iv size() const
Definition: SIndex.hpp:681
container_t IndexList
Definition: SIndex.h:289
container_t::size_type size_type_iv
Definition: SIndex.h:73
const unsigned Dim
NDIndex< Dim > BoundingBox
Definition: SIndex.h:286
Definition: Inform.h:41
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
void setup()
Definition: SIndex.hpp:137