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