OPAL (Object Oriented Parallel Accelerator Library) 2022.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
38template<unsigned int Dim>
39SIndex<Dim>::SIndex() : Layout(0) {
40
41}
42
43
45// constructor: requires a FieldLayout, and optionally an offset amount
46template<unsigned int Dim>
48
49
50
51 setup();
52}
53
54
56// copy constructor
57template<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.
74template<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.
94template<unsigned int Dim>
95SIndex<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
112template<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
123template<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.
136template<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)
159template<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)
181template<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).
202template<unsigned int Dim>
203void 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)
241template<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)
261template<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).
278template<unsigned int Dim>
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.
317template<unsigned int Dim>
318void 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
331template<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
344template<unsigned int Dim>
345bool 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
359template<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.
388template<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.
407template<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
426template<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.
460template<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
477template<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.
510template<unsigned int Dim>
512
513
514
515 if (&si != this) {
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.
537template<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
554template<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)
572template<unsigned int Dim>
574
575
576
577 CTAssert(Dim==1);
578 return SIndex(*this, SOffset<Dim>(i0));
579}
580
581template<unsigned int Dim>
583
584
585 CTAssert(Dim==2);
586 return SIndex(*this, SOffset<Dim>(i0,i1));
587}
588
589template<unsigned int Dim>
590SIndex<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
598template<unsigned int Dim>
599SIndex<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
607template<unsigned int Dim>
608SIndex<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
616template<unsigned int Dim>
617SIndex<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
626template<unsigned int Dim>
628
629
630
631 return SIndex(*this, so);
632}
633
634template<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
648template<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
663template<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
677template<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.
694template<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
712template<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
728template<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
740template<unsigned int Dim>
741std::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
763template<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 ***************************************************************************/
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
const unsigned Dim
std::ostream & operator<<(std::ostream &o, const SIndex< Dim > &si)
Definition: SIndex.hpp:741
std::complex< double > a
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define CTAssert(c)
Definition: PAssert.h:35
Definition: Offset.h:66
unsigned size() const
iterator_iv end_iv()
Definition: FieldLayout.h:716
ac_id_vnodes::iterator iterator_iv
Definition: FieldLayout.h:73
Definition: Index.h:237
container_t::const_iterator const_iterator
Definition: LSIndex.h:38
container_t::size_type size_type
Definition: LSIndex.h:39
Definition: SIndex.h:64
container_t::iterator iterator_iv
Definition: SIndex.h:70
virtual ~SIndex()
Definition: SIndex.hpp:113
size_type_iv size_iv() const
Definition: SIndex.h:249
SIndex()
Definition: SIndex.hpp:39
bool addIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:160
void initialize(FieldLayout< Dim > &)
Definition: SIndex.hpp:124
iterator_iv end_iv()
Definition: SIndex.h:246
container_t::size_type size_type_iv
Definition: SIndex.h:72
FieldLayout< Dim > * Layout
Definition: SIndex.h:276
size_type_iv size() const
Definition: SIndex.hpp:678
bool removeIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:242
container_t IndexList
Definition: SIndex.h:283
void printDebug(Inform &) const
Definition: SIndex.hpp:764
void setup()
Definition: SIndex.hpp:137
const NDIndex< Dim > & getDomain() const
Definition: SIndex.h:153
bool hasIndex(const SOffset< Dim > &) const
Definition: SIndex.hpp:345
virtual void notifyUserOfDelete(UserList *)
Definition: SIndex.hpp:729
SIndex< Dim > & operator=(const PETE_Expr< T1 > &rhs)
Definition: SIndex.h:98
container_t::const_iterator const_iterator_iv
Definition: SIndex.h:71
IndexedSIndex< Dim, 1 > operator[](const Index &)
Definition: SIndex.hpp:649
SOffset< Dim > & getOffset()
Definition: SIndex.h:143
virtual void Repartition(UserList *)
Definition: SIndex.hpp:713
SOffset< Dim > Offset
Definition: SIndex.h:280
SIndex< Dim > operator()(int)
Definition: SIndex.hpp:573
iterator_iv begin_iv()
Definition: SIndex.h:245
void clear()
Definition: SIndex.hpp:332
SIndex< Dim > & operator&=(const SIndex< Dim > &)
Definition: SIndex.hpp:427
NDIndex< Dim > BoundingBox
Definition: SIndex.h:288
void setFieldLayout(FieldLayout< Dim > &)
Definition: SIndex.hpp:695
void toNDIndex(const SOffset< Dim > &, NDIndex< Dim > &)
Definition: SIndex.hpp:664
void reserve(double=1.0)
Definition: SIndex.hpp:318
SIndex< Dim > & operator|=(const SIndex< Dim > &)
Definition: SIndex.hpp:511
Definition: Inform.h:42
ID_t getUserListID() const
Definition: UserList.cpp:54