OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
SIndex.h
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  *
7  * Visit http://people.web.psi.ch/adelmann/ for more details
8  *
9  ***************************************************************************/
10 
11 #ifndef SINDEX_H
12 #define SINDEX_H
13 
14 // include files
15 #include "Index/NDIndex.h"
16 #include "Index/SOffset.h"
17 #include "Index/LSIndex.h"
19 #include "Utility/RefCounted.h"
20 #include "Utility/Inform.h"
21 #include <memory>
22 
23 #include <vector>
24 #include <iostream>
25 
26 // forward declarations
27 template <unsigned Dim> class FieldLayout;
28 template <unsigned Dim> class SIndex;
29 template <unsigned Dim, unsigned Brackets> class IndexedSIndex;
30 template <unsigned Dim>
31 std::ostream& operator<<(std::ostream&, const SIndex<Dim>&);
32 
33 /***********************************************************************
34  *
35  * SIndex represents a set of single-point indices for a Field, which
36  * are used to implement sparse-index operations. The user creates an
37  * SIndex object through a where statement or by just adding individual
38  * points, and then performs operations using the SIndex object just as
39  * is done with a regular Index object. In that case, operations are
40  * only performed on those elements of the LHS which are in the SIndex
41  * list. Stencil operations are represented by using SOffset objects
42  * to indicate offsets from the SIndex indices.
43  *
44  * Initially, an SIndex object is empty; points must be added to it by
45  * calling addIndex. An SIndex has an offset, set (or changed) by
46  * calling setOffset(const SOffset&). Only indices for local vnodes are
47  * stored in this object; adding other points will return an error flag.
48  *
49  * Constructing an SIndex requires a FieldLayout object, since SIndex
50  * needs to know the range of index values for which is can store points,
51  * and the location of vnodes.
52  *
53  * A note about offsets: the offset factor is used primarily to make
54  * it possible to specify index offsets in expressions for stenciling
55  * purposes. The method for adding an offset to an SIndex is via the
56  * + or - operators, e.g., A[si] = B[si + SOffset<Dim>(1,-1)], or via
57  * the () operator, e.g., A[si] = B[si(1,-1)] (which means the same as
58  * above). Otherwise, the user should not specify an offset, and the
59  * operations such as union, intersection, etc. implicitly assume that
60  * the offset is zero for the LHS and the RHS.
61  *
62  ***********************************************************************/
63 
64 template <unsigned Dim>
65 class SIndex : public FieldLayoutUser {
66 
67 public:
68  //# public typedefs
69  typedef std::vector< std::shared_ptr<LSIndex<Dim> > > container_t;
70  typedef unsigned int size_type;
72  typedef typename container_t::const_iterator const_iterator_iv;
73  typedef typename container_t::size_type size_type_iv;
76 
77  // default constructor: this requires the user to call 'initialize'
78  // before any other actions are carried out with this SIndex
79  SIndex();
80 
81  // constructor: requires a FieldLayout
83 
84  // copy constructor
85  SIndex(const SIndex<Dim>&);
86 
87  // destructor: frees memory used to store indices, and check out from Layout
88  virtual ~SIndex();
89 
90  // initialize the object, if it was constructed with the default
91  // constructor
93 
94  // report if we need initialization
95  bool needInitialize() const { return (Layout == 0); }
96 
97  // a templated operator= taking a PETE expression
98  template<class T1>
100  assign(*this, rhs);
101  return *this;
102  }
103 
104  // assignment operator, with another SIndex or SOffset object. If an
105  // NDIndex object is given, all the points in the NDIndex are used.
109 
110  // intersection operator, with another SIndex or SOffset object.
111  // intersected SIndexes must have the same layout; intersection with an
112  // SOffset will leave this object with at most one point
116 
117  // union operator, with another SIndex or SOffset object. This will
118  // append the point if it is not already present.
122 
123  // add a new index point, specified as an Offset or as a single-point NDIndex
124  // return success (this can fail if the point is outsize the field's domain)
125  bool addIndex(const SOffset<Dim>&);
126  bool addIndex(iterator_iv&, const SOffset<Dim>&);
127  void addIndex(const NDIndex<Dim>&);
128 
129  // remove an index point, specified as an Offset or as a single-point NDIndex
130  // return success (this can fail if the point is not on this node)
131  bool removeIndex(const SOffset<Dim>&);
132  bool removeIndex(iterator_iv&, const SOffset<Dim>&);
133  void removeIndex(const NDIndex<Dim>&);
134 
135  // reserve storage space equal to the given fraction of the size of
136  // each vnode. if fraction=1.0, reserve storage for the entire vnode.
137  void reserve(double = 1.0);
138 
139  // clear out the existing indices
140  void clear();
141 
142  // get the offset for this sparse index. You can change the offset by
143  // retrieving it this way and then adding to it.
145  const SOffset<Dim>& getOffset() const { return Offset; }
146 
147  // get the FieldLayout we are using
148  FieldLayout<Dim>& getFieldLayout() const { return *Layout; };
149 
150  // change to using a new layout.
152 
153  // get or change the 'bounding box' domain of this SIndex
154  const NDIndex<Dim> &getDomain() const { return BoundingBox; }
155  void setDomain(const NDIndex<Dim> &ndi) { BoundingBox = ndi; }
156 
157  //
158  // SIndex <--> SOffset operations
159  //
160 
161  // add or subtract a given offset
162  // SIndex<Dim>& operator+=(const SOffset<Dim>& so) {Offset+=so;return *this;}
163  // SIndex<Dim>& operator-=(const SOffset<Dim>& so) {Offset-=so;return *this;}
164  friend
166  return SIndex(si, so);
167  }
168 
169  friend
171  return SIndex(si, so);
172  }
173 
174  friend
175  SIndex<Dim> operator+(const SIndex<Dim>& si, const int *so) {
176  return SIndex(si, so);
177  }
178 
179  friend
180  SIndex<Dim> operator+(const int *so, const SIndex<Dim>& si) {
181  return SIndex(si, so);
182  }
183 
184  friend
186  return SIndex(si, -so);
187  }
188 
189  friend
191  return SIndex(si, -so);
192  }
193 
194  friend
195  SIndex<Dim> operator-(const SIndex<Dim>& si, const int *so) {
196  return SIndex(si, -SOffset<Dim>(so));
197  }
198 
199  friend
200  SIndex<Dim> operator-(const int *so, const SIndex<Dim>& si) {
201  return SIndex(si, -SOffset<Dim>(so));
202  }
203 
204  // () operators which make a copy of this SIndex with an extra offset.
205  // These are functionally identical to the operator+, but provide a
206  // nicer syntax. That is, si(1,1) means si + SOffset<Dim>(1,1)
207  SIndex<Dim> operator()(int);
208  SIndex<Dim> operator()(int,int);
209  SIndex<Dim> operator()(int,int,int);
210  SIndex<Dim> operator()(int,int,int,int);
211  SIndex<Dim> operator()(int,int,int,int,int);
212  SIndex<Dim> operator()(int,int,int,int,int,int);
214  SIndex<Dim> operator()(const int *);
215 
216  // operator[], which is used with Index or NDIndex objects to further
217  // subset the data. This will only work if the dimension of the Index
218  // arguments + Brackets is <= Dim. Otherwise, too many dimensions worth
219  // of Index objects are being applied
221 
222  template<unsigned int Dim2>
224 
225 
226 
227  CTAssert(Dim >= Dim2);
228  NDIndex<Dim> dom;
229  for (unsigned int i=0; i < Dim2; ++i)
230  dom[i] = ndi[i];
231  return IndexedSIndex<Dim,Dim2>(*this, dom);
232  }
233 
234  //
235  // SIndex <--> NDIndex operations
236  //
237 
238  // convert from the given SOffset value to an NDIndex, with offset added
239  void toNDIndex(const SOffset<Dim>&, NDIndex<Dim>&);
240 
241  //
242  // container methods
243  //
244 
245  // return begin/end iterators for the LSIndex container
246  iterator_iv begin_iv() { return IndexList.begin(); }
247  iterator_iv end_iv() { return IndexList.end(); }
248  const_iterator_iv begin_iv() const { return IndexList.begin(); }
249  const_iterator_iv end_iv() const { return IndexList.end(); }
250  size_type_iv size_iv() const { return IndexList.size(); }
251 
252  // return the total size, which is the sum of the individual sizes
253  size_type_iv size() const;
254 
255  // return whether the given point is contained here
256  bool hasIndex(const SOffset<Dim>&) const;
257 
258  //
259  // virtual functions for FieldLayoutUser's
260  //
261 
262  // Repartition onto a new layout
263  virtual void Repartition(UserList *);
264 
265  // Tell this object that an object is being deleted
266  virtual void notifyUserOfDelete(UserList *);
267 
268  //
269  // I/O
270  //
271 
272  // print out debugging info
273  void printDebug(Inform&) const;
274 
275 private:
276  // our FieldLayout, indicating the extent and distrib. of index space
278 
279  // our current offset; by default, this is zero. We keep a special flag
280  // to indicate whether it is zero or not.
282 
283  // our 'bounding box', which is the region that is or should be iterated
284  // over to determine what points are in this sparse index list. By default,
285  // this is the domain of the FieldLayout
287 
288  // our list of indices for each local vnode
290 
291  // a special constructor, taking another SIndex and an Offset. This
292  // version is almost like a copy constructor, except that the given Offset
293  // is added in to the offset from the copied SIndex.
294  SIndex(const SIndex<Dim>&, const SOffset<Dim>&);
295  SIndex(const SIndex<Dim>&, const int *);
296 
297  // set up our internal data structures from the constructor. Assumes
298  // the Layout and Offset have been set.
299  void setup();
300 };
301 
302 #include "Index/SIndex.hpp"
303 
304 #endif // SINDEX_H
305 
306 /***************************************************************************
307  * $RCSfile: SIndex.h,v $ $Author: adelmann $
308  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $
309  * IPPL_VERSION_ID: $Id: SIndex.h,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $
310  ***************************************************************************/
void printDebug(Inform &) const
Definition: SIndex.hpp:767
LSIndex< Dim >::iterator iterator_indx
Definition: SIndex.h:74
Definition: PETE.h:80
void setDomain(const NDIndex< Dim > &ndi)
Definition: SIndex.h:155
void toNDIndex(const SOffset< Dim > &, NDIndex< Dim > &)
Definition: SIndex.hpp:667
size_type_iv size_iv() const
Definition: SIndex.h:250
LSIndex< Dim >::const_iterator const_iterator_indx
Definition: SIndex.h:75
Definition: SIndex.h:28
void reserve(double=1.0)
Definition: SIndex.hpp:320
void setFieldLayout(FieldLayout< Dim > &)
Definition: SIndex.hpp:698
const_iterator_iv end_iv() const
Definition: SIndex.h:249
container_t::const_iterator const_iterator
Definition: LSIndex.h:39
IndexedSIndex< Dim, Dim2 > operator[](const NDIndex< Dim2 > &ndi)
Definition: SIndex.h:223
#define CTAssert(c)
Definition: PAssert.h:40
void assign(const BareField< T, Dim > &a, RHS b, OP op, ExprTag< true >)
friend SIndex< Dim > operator-(const SOffset< Dim > &so, const SIndex< Dim > &si)
Definition: SIndex.h:190
virtual void notifyUserOfDelete(UserList *)
Definition: SIndex.hpp:732
friend SIndex< Dim > operator+(const SOffset< Dim > &so, const SIndex< Dim > &si)
Definition: SIndex.h:170
container_t::const_iterator const_iterator_iv
Definition: SIndex.h:72
virtual ~SIndex()
Definition: SIndex.hpp:113
friend SIndex< Dim > operator-(const SIndex< Dim > &si, const int *so)
Definition: SIndex.h:195
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
friend SIndex< Dim > operator+(const SIndex< Dim > &si, const int *so)
Definition: SIndex.h:175
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
unsigned int size_type
Definition: SIndex.h:70
Definition: Index.h:236
container_t::iterator iterator_iv
Definition: SIndex.h:71
SOffset< Dim > & getOffset()
Definition: SIndex.h:144
void clear()
Definition: SIndex.hpp:334
const NDIndex< Dim > & getDomain() const
Definition: SIndex.h:154
bool hasIndex(const SOffset< Dim > &) const
Definition: SIndex.hpp:348
friend SIndex< Dim > operator-(const SIndex< Dim > &si, const SOffset< Dim > &so)
Definition: SIndex.h:185
container_t::iterator iterator
Definition: LSIndex.h:38
SIndex< Dim > & operator&=(const SIndex< Dim > &)
Definition: SIndex.hpp:430
FieldLayout< Dim > & getFieldLayout() const
Definition: SIndex.h:148
SIndex< Dim > operator()(int)
Definition: SIndex.hpp:576
iterator_iv end_iv()
Definition: SIndex.h:247
void initialize(FieldLayout< Dim > &)
Definition: SIndex.hpp:124
friend SIndex< Dim > operator+(const SIndex< Dim > &si, const SOffset< Dim > &so)
Definition: SIndex.h:165
IndexedSIndex< Dim, 1 > operator[](const Index &)
Definition: SIndex.hpp:652
SIndex< Dim > & operator|=(const SIndex< Dim > &)
Definition: SIndex.hpp:514
const SOffset< Dim > & getOffset() const
Definition: SIndex.h:145
virtual void Repartition(UserList *)
Definition: SIndex.hpp:716
friend SIndex< Dim > operator+(const int *so, const SIndex< Dim > &si)
Definition: SIndex.h:180
size_type_iv size() const
Definition: SIndex.hpp:681
std::vector< std::shared_ptr< LSIndex< Dim > > > container_t
Definition: SIndex.h:69
container_t IndexList
Definition: SIndex.h:289
std::string::iterator iterator
Definition: MSLang.h:16
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
const_iterator_iv begin_iv() const
Definition: SIndex.h:248
friend SIndex< Dim > operator-(const int *so, const SIndex< Dim > &si)
Definition: SIndex.h:200
bool needInitialize() const
Definition: SIndex.h:95
void setup()
Definition: SIndex.hpp:137