OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
SIndexAssign.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/SIndexAssign.h"
28 #include "Index/SIndex.h"
29 #include "Field/BrickIterator.h"
30 // #include "Field/Field.h"
31 // #include "Field/IndexedField.h"
32 // #include "Field/Assign.h"
33 #include "Utility/IpplInfo.h"
34 
35 
36 
38 // a simple class to apply the assign function to one point of the
39 // assignment domain.
40 template<unsigned int Dim, class OP>
42 
43 
45 // a specialization of the simple class to apply the regular assign
46 // function to one point of the assignment domain.
47 
48 template<unsigned int Dim>
50 public:
51  // initially, the sparse index container must be cleared out
52  static void initialize(SIndex<Dim>& s) { s.clear(); }
53 
54  // S = exp means we cleared out all the points previously, so we know
55  // we do not need to worry about repeated points
56  static void apply(SIndex<Dim>& /*SI*/,
57  typename SIndex<Dim>::iterator_iv& LSI,
58  const SOffset<Dim>& SO,
59  bool result) {
60  if (result) {
61  // we can just add the index to the LSIndex's list here, for the
62  // following reasons:
63  // 1. We did a 'clear' before the expression started (when
64  // initialize was called), so all the LSIndex objects in this
65  // SIndex are separate, empty items, not references to other
66  // SIndex lists.
67  // 2. We know this point is unique, since we did a clear and then
68  // looped over completely different points in the expression
69  // evaluation.
70  // 3. We are sure this point belongs to this LSIndex, since we
71  // iterate over the vnodes of the SIndex.
72  (*LSI)->addIndex(SO);
73  }
74  }
75 };
76 
77 
79 // a specialization of the simple class to apply the bitwise AND assign
80 // function to one point of the assignment domain.
81 
82 template<unsigned int Dim>
84 public:
85  // since we do an intersection, we must keep the existing data
86  static void initialize(SIndex<Dim>&) { }
87 
88  // S &= expr means 'intersection' ... only keep the point if result is
89  // true, remove the point if result is false
90  static void apply(SIndex<Dim>& SI,
91  typename SIndex<Dim>::iterator_iv& LSI,
92  const SOffset<Dim>& SO,
93  bool result) {
94  if (!result && (*LSI)->hasIndex(SO)) {
95  // we must call removeIndex in SIndex (and not in LSIndex) here
96  // because we might need to make a copy of the LSIndex data
97  // first (copy-on-write). This will be slower than doing some
98  // form of direct assignment.
99  SI.removeIndex(LSI, SO);
100  }
101  }
102 };
103 
104 
106 // a specialization of the simple class to apply the bitwise OR assign
107 // function to one point of the assignment domain.
108 
109 template<unsigned int Dim>
111 public:
112  // since we do a union, we must keep the existing data
113  static void initialize(SIndex<Dim>&) { }
114 
115  // S |= expr means 'union' ... we add points as normal, but we did not
116  // clear out the points that were there previously
117  static void apply(SIndex<Dim>& SI,
118  typename SIndex<Dim>::iterator_iv& LSI,
119  const SOffset<Dim>& SO,
120  bool result) {
121 
122  if (result && ! (*LSI)->hasIndex(SO)) {
123  // we must call addIndex in SIndex (and not in LSIndex) here
124  // because we need to check if this point SO is already in the
125  // list of points. This will be slower than doing some form
126  // of direct assignment.
127  SI.addIndex(LSI, SO);
128  }
129  }
130 };
131 
132 
134 // a simple class to do different dimension-specific loops in an
135 // SIndex expression.
136 template<class OP, unsigned int Dim>
138 public:
139  // the general loop; this is done for 4D or higher dimensions
140  template<class RHS>
141  static void evaluate(SIndex<Dim>& si, typename SIndex<Dim>::iterator_iv& lsi,
142  NDIndex<Dim>& dom, RHS& Rhs) {
143 
144  int n0 = dom[0].length();
145  int n1 = dom[1].length();
146  int n2 = dom[2].length();
147  if (n0 > 0 && n1 > 0 && n2 > 0) {
148  BrickCounter<Dim> count(dom); // ada: changed from cdom to dom, cdom does not make sense!
149  ERRORMSG("changed from cdom to dom, cdom does not make sense! (SindexAssign.cpp)" << endl);
150 
151  unsigned d;
153  for (d=3; d < Dim; ++d)
154  so[d] = dom[d].first();
155  do {
156  Index::iterator x2 = dom[2].begin();
157  for (int i2=0; i2<n2; ++i2, ++x2) {
158  so[2] = *x2;
159  Index::iterator x1 = dom[1].begin();
160  for (int i1=0; i1<n1; ++i1, ++x1) {
161  so[1] = *x1;
162  Index::iterator x0 = dom[0].begin();
163  for (int i0=0; i0<n0; ++i0, ++x0) {
164  so[0] = *x0;
165  bool result = (for_each(Rhs, EvalFunctor_3(i0,i1,i2)) != false);
166  SIndexAssignTraits<3U,OP>::apply(si, lsi, so, result);
167  }
168  }
169  }
170 
171  for (d=3; d<Dim; ++d) {
172  count.step(d);
173  so[d] += dom[d].stride();
175  if ( ! count.done(d) )
176  break;
177  count.rewind(d);
178  so[d] = dom[d].first();
180  }
181 
182  } while (d<Dim);
183  }
184  }
185 };
186 
187 
189 //a specialization of SIndexAssignLoop for a 1D loop evaluation NOTE:
190 //dom must be within the local domain of the given LSIndex
191 template<class OP>
192 class SIndexExpLoop<OP,1U> {
193 public:
194  template<class RHS>
196  NDIndex<1U>& dom, RHS& Rhs) {
197 
198  int n0 = dom[0].length();
199  if (n0 > 0) {
200  Index::iterator x0 = dom[0].begin();
201  for (int i0 = 0; i0 < n0; ++i0, ++x0) {
202  bool result = (for_each(Rhs, EvalFunctor_1(i0)) != false);
203  SIndexAssignTraits<1U,OP>::apply(si, lsi, SOffset<1>(*x0), result);
204  }
205  }
206  }
207 };
208 
209 
211 // a specialization of SIndexAssignLoop for a 2D loop evaluation
212 // NOTE: dom must be within the local domain of the given LSIndex
213 template<class OP>
214 class SIndexExpLoop<OP,2U> {
215 public:
216  template<class RHS>
218  NDIndex<2U>& dom, RHS& Rhs) {
219 
220  int n0 = dom[0].length();
221  int n1 = dom[1].length();
222  if (n0 > 0 && n1 > 0) {
223  Index::iterator x1 = dom[1].begin();
224  for (int i1 = 0; i1 < n1; ++i1, ++x1) {
225  Index::iterator x0 = dom[0].begin();
226  for (int i0 = 0; i0 < n0; ++i0, ++x0) {
227  bool result = (for_each(Rhs, EvalFunctor_2(i0,i1)) != false);
228  SIndexAssignTraits<2U,OP>::apply(si, lsi, SOffset<2>(*x0, *x1),
229  result);
230  }
231  }
232  }
233  }
234 };
235 
236 
238 // a specialization of SIndexAssignLoop for a 3D loop evaluation
239 // NOTE: dom must be within the local domain of the given LSIndex
240 template<class OP>
241 class SIndexExpLoop<OP,3U> {
242 public:
243  template<class RHS>
245  NDIndex<3U>& dom, RHS& Rhs) {
246 
247  int n0 = dom[0].length();
248  int n1 = dom[1].length();
249  int n2 = dom[2].length();
250  if (n0 > 0 && n1 > 0 && n2 > 0) {
251  Index::iterator x2 = dom[2].begin();
252  for (int i2 = 0; i2 < n2; ++i2, ++x2) {
253  Index::iterator x1 = dom[1].begin();
254  for (int i1 = 0; i1 < n1; ++i1, ++x1) {
255  Index::iterator x0 = dom[0].begin();
256  for (int i0 = 0; i0 < n0; ++i0, ++x0) {
257  bool result = (for_each(Rhs, EvalFunctor_3(i0,i1,i2)) != false);
259  SOffset<3>(*x0, *x1, *x2),
260  result);
261  }
262  }
263  }
264  }
265  }
266 };
267 
268 
270 // The 'assign' function for SIndex objects must handle two situations,
271 // one where the RHS is a simple, full-field expression, and one where
272 // the RHS is a complex, indexed expression. The 'AssignActions'
273 // struct is specialized on the 'SiExprTag<bool>' class to perform
274 // different setup and cleaup operations for the RHS objects based on
275 // whether the expression is simple (bool=false) or indexed (bool=true).
276 
277 template<unsigned Dim, class T>
278 struct AssignActions { };
279 
280 template<unsigned Dim>
281 struct AssignActions<Dim, SIExprTag<true> > {
282  template<class RHS>
283  static void fillgc(RHS &bb, const NDIndex<Dim> & /*domain*/) {
284  // ask each field on the RHS to fill its guard cells, if necessary
285  //tjw3/3/99 for_each(bb, FillGCIfNecessary(domain), PETE_NullCombiner());
287  }
288 
289  template<class RHS>
290  static bool plugbase(RHS &bb, const NDIndex<Dim> &domain) {
291  // ask each RHS field to set itself up to iterate over the given locdomain.
292  // if any cannot, this will return false.
293  return for_each(bb, PlugBase<Dim>(domain), PETE_AndCombiner());
294  }
295 
296  template<class RHS>
297  static void nextLField(RHS &) {
298  // in this case, there is nothing to do, since PlugBase always ends
299  // up setting which LField to use
300  }
301 };
302 
303 template<unsigned Dim>
304 struct AssignActions<Dim, SIExprTag<false> > {
305  template<class RHS>
306  static void fillgc(RHS &bb, const NDIndex<Dim> &) {
307  // ask each field on the RHS to fill its guard cells, if necessary
308  // here, it cannot be a stencil, so not necessary
309  //tjw 3/3/99, add:
311  //tjw 3/3/99, add.
312  }
313 
314  template<class RHS>
315  static bool plugbase(RHS &bb, const NDIndex<Dim> &) {
316  // tell each RHS field to reset to the beginning of it's current LField
318  return true;
319  }
320 
321  template<class RHS>
322  static void nextLField(RHS &bb) {
323  // tell each RHS field to move on to the next LField
325  }
326 };
327 
328 
330 // assign values to an SIndex: evaluate the RHS at all the points in
331 // the given domain, find where it evaluates to true, and store the
332 // value of that index point.
333 template<unsigned Dim, class RHS, class Op, bool IsExpr>
334 void assign(SIndex<Dim>& a, RHS b, Op, const NDIndex<Dim> &domain,
335  SIExprTag<IsExpr> /*isexpr*/) {
336 
337 
338 
339 
340  // Inform dbgmsg("SIndex assign", INFORM_ALL_NODES);
341  // dbgmsg << "Computing on total domain = " << domain << endl;
342 
343  // unwrap the PETE expression object to get what we're computing with
344  typename RHS::Wrapped& bb = b.PETE_unwrap();
345 
346  // initialize the SIndex for this operation
348 
349  // Fill GC's, if necessary
350  AssignActions<Dim,SIExprTag<IsExpr> >::fillgc(bb, domain);
351 
352  // iterate through all the local vnodes in the FieldLayout used
353  // by the SIndex, and look at the points in these domains
354  typename SIndex<Dim>::iterator_iv la = a.begin_iv();
355  typename SIndex<Dim>::iterator_iv aend = a.end_iv();
356  for ( ; la != aend; ++la ) {
357  // check if we have any points in this LField to process
358  NDIndex<Dim> locdomain = domain.intersect((*la)->getDomain());
359  //dbgmsg << "Doing LField " << (*la)->getDomain() << " with intersection ";
360  //dbgmsg << locdomain << endl;
361 
362  // only proceed if we have any intersecting points
363  if (!locdomain.empty()) {
364  // First look and see if the arrays are sufficiently aligned to do
365  // this in one shot. We do this by trying to do a plugBase and
366  // seeing if it worked.
367  if (AssignActions<Dim,SIExprTag<IsExpr> >::plugbase(bb, locdomain)) {
368 
369  // check if the RHS is compressed and we can do a compressed assign
370  if (OperatorTraits<Op>::IsAssign && locdomain == (*la)->getDomain() &&
372  // why yes we can ... tell the SIndex to store the results for
373  // the entire vnode in one shot
374  bool result = (for_each(bb, EvalFunctor_0()) != false);
375  (*la)->Compress(result);
376 
377  //NDIndex<Dim>& dom = (NDIndex<Dim>&) ((*la)->getDomain());
378  //dbgmsg << "compressed in dom = " << dom << ", result = " << result;
379  //dbgmsg << endl;
380  } else {
381  // perform actions to find necessary points in the current Vnode
382  // of the SIndex, by looping over the domain and seeing where
383  // the RHS == true
384  SIndexExpLoop<Op,Dim>::evaluate(a, la, locdomain, bb);
385 
386  //NDIndex<Dim>& dom = (NDIndex<Dim>&) ((*la)->getDomain());
387  //dbgmsg << "uncompressed in dom = " << dom << endl;
388  }
389  } else {
390  ERRORMSG("All Fields in an expression must be aligned. ");
391  ERRORMSG("(Do you have enough guard cells?)" << endl);
392  ERRORMSG("This error occurred while evaluating an SIndex expression ");
393  ERRORMSG("for an LField with domain " << (*la)->getDomain() << endl);
394  Ippl::abort();
395  }
396  // } else {
397  // dbgmsg << " ... intersection is empty." << endl;
398  }
399 
400  // move the RHS Field's on to the next LField, if necessary
401  AssignActions<Dim,SIExprTag<IsExpr> >::nextLField(bb);
402  }
403 
404  // at the end, tell the SIndex we used this domain, so that should be
405  // its new bounding box
406  a.setDomain(domain);
407 }
408 
409 
410 /***************************************************************************
411  * $RCSfile: SIndexAssign.cpp,v $ $Author: adelmann $
412  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $
413  * IPPL_VERSION_ID: $Id: SIndexAssign.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $
414  ***************************************************************************/
void setDomain(const NDIndex< Dim > &ndi)
Definition: SIndex.h:154
static void fillgc(RHS &bb, const NDIndex< Dim > &)
bool addIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:160
bool removeIndex(const SOffset< Dim > &)
Definition: SIndex.hpp:242
void step(unsigned d)
Definition: BrickIterator.h:39
NDIndex< Dim > intersect(const NDIndex< Dim > &) const
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
void assign(const BareField< T, Dim > &a, RHS b, OP op, ExprTag< true >)
static void initialize(SIndex< Dim > &)
static void apply(SIndex< Dim > &, typename SIndex< Dim >::iterator_iv &LSI, const SOffset< Dim > &SO, bool result)
container_t::iterator iterator_iv
Definition: SIndex.h:70
static void initialize(SIndex< Dim > &s)
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
static bool plugbase(RHS &bb, const NDIndex< Dim > &)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
static void evaluate(SIndex< Dim > &si, typename SIndex< Dim >::iterator_iv &lsi, NDIndex< Dim > &dom, RHS &Rhs)
void clear()
Definition: SIndex.hpp:332
bool empty() const
PETE_Combiner< bool, OpAnd > PETE_AndCombiner
Definition: PETE.h:467
static void evaluate(SIndex< 1U > &si, SIndex< 1U >::iterator_iv &lsi, NDIndex< 1U > &dom, RHS &Rhs)
const unsigned Dim
iterator_iv begin_iv()
Definition: SIndex.h:245
float result
Definition: test.py:2
Definition: SIndex.h:27
static void apply(SIndex< Dim > &SI, typename SIndex< Dim >::iterator_iv &LSI, const SOffset< Dim > &SO, bool result)
static void apply(SIndex< Dim > &SI, typename SIndex< Dim >::iterator_iv &LSI, const SOffset< Dim > &SO, bool result)
static void fillgc(RHS &bb, const NDIndex< Dim > &)
void rewind(unsigned d)
Definition: BrickIterator.h:40
static void initialize(SIndex< Dim > &)
static void evaluate(SIndex< 2U > &si, SIndex< 2U >::iterator_iv &lsi, NDIndex< 2U > &dom, RHS &Rhs)
bool done(unsigned d) const
Definition: BrickIterator.h:36
bool for_each(const BareFieldIterator< T, D > &p, SameFieldID s, C)
Definition: AssignDefs.h:30
iterator_iv end_iv()
Definition: SIndex.h:246
static void evaluate(SIndex< 3U > &si, SIndex< 3U >::iterator_iv &lsi, NDIndex< 3U > &dom, RHS &Rhs)
static bool plugbase(RHS &bb, const NDIndex< Dim > &domain)
static void abort(const char *=0)
Definition: IpplInfo.cpp:616
FillGCIfNecessaryTag< D, T1 > FillGCIfNecessary(const BareField< T1, D > &bf)
Definition: AssignTags.h:126