OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Assign.hpp
Go to the documentation of this file.
1 /***************************************************************************
2  *
3  * The IPPL Framework
4  *
5  ***************************************************************************/
6 
8 //
9 // This file contains the versions of assign() that work with expressions
10 // on the RHS. They do not handle general communications, and require
11 // sufficient guard cells to cover any stencil-like access.
12 //
14 
15 // include files
16 #include "Field/Assign.h"
17 #include "Field/AssignDefs.h"
18 #include "Field/BareField.h"
19 #include "Field/BrickExpression.h"
20 #include "Field/IndexedBareField.h"
21 #include "Field/LField.h"
22 #include "Message/Communicate.h"
23 #include "Message/Message.h"
24 #include "Utility/PAssert.h"
25 #include "Utility/IpplInfo.h"
26 #include "Utility/IpplStats.h"
27 
28 #include "PETE/IpplExpressions.h"
29 
30 #include <map>
31 #include <vector>
32 #include <functional>
33 #include <utility>
34 #include <iostream>
35 #include <typeinfo>
36 
38 //
39 // TryCompressLhs.
40 //
41 // Encodes the logic for whether to compress or uncompress the
42 // left hand side given information about the expression.
43 //
45 
46 template<class T, unsigned Dim, class A, class Op>
47 bool
48 TryCompressLHS(LField<T,Dim>& lf, A& rhs, Op op, const NDIndex<Dim>& domain)
49 {
50 
51  // just skip this if we can
53  return(false);
54 
55  // debugging output macros. these are only enabled if DEBUG_ASSIGN is
56  // defined.
57  ASSIGNMSG(Inform msg("TryCompressLHS", INFORM_ALL_NODES));
58  ASSIGNMSG(msg << "Checking for compressibility of LField with domain = ");
59  ASSIGNMSG(msg << lf.getOwned() << " over assignment domain = " << domain);
60  ASSIGNMSG(msg << endl);
61 
62  // If the right hand side is compressed and we are looking at
63  // the whole domain for the lhs, we have a chance of
64  // being able to compress the left hand side.
65  // Then if it is simple assign or if the lhs is already compressed
66  // we can do a compressed assign.
67  bool c1 = for_each(rhs,IsCompressed(),PETE_AndCombiner());
68  bool c2 = domain.containsAllPoints(lf.getOwned());
70  bool c4 = lf.IsCompressed();
71  bool compress = c1 && c2 && ( c3 || c4 );
72 
73  ASSIGNMSG(msg << " RHS IsCompressed() = " << c1 << endl);
74  ASSIGNMSG(msg << " LHS IsCompressed() = " << c4 << endl);
75  ASSIGNMSG(msg << "domain.contains(lhs) = " << c2 << endl);
76  ASSIGNMSG(msg << " IsAssign = " << c3 << endl);
77  ASSIGNMSG(msg << " result = " << compress << endl);
78 
79  // If we decide it can be compressed, do it, otherwise undo it.
80  if (compress)
81  {
82  // We can compress this, so compress it down using first element
83  // as the compression value.
84  ASSIGNMSG(msg << "Yes we CAN compress, so do so now ... ");
85  lf.Compress();
86  ASSIGNMSG(msg << "now, compressed value = " << *lf.begin() << endl);
87  return true;
88  }
89 
90  // We can't compress the LHS. Check if both sides are compressed already
91  // and have the same value, and we're doing assignment (that is, check
92  // if we're trying to assign the same value to a portion of an already
93  // compressed region). Note that if this is true, we know that the op
94  // is for assignment.
95  if (c1 && c3 && c4)
96  {
97  T tmpval{};
98  PETE_apply(op, tmpval, for_each(rhs, EvalFunctor_0()));
99  if (*lf.begin() == tmpval)
100  {
101  // Both sides are compressed, and we're doing assignment, but the
102  // domains don't fully intersect. We can still deal with this as
103  // a compressed entity if the LHS compressed value equals the RHS
104  // compressed value.
105  ASSIGNMSG(msg << "LHS and RHS are compressed, doing assign, and ");
106  ASSIGNMSG(msg << *lf.begin() << " == " <<tmpval<<", so result = 1");
107  ASSIGNMSG(msg << endl);
108  return true;
109  }
110  }
111 
112  // OK we need to uncompress the LHS, but we might not need to keep the data.
113  // If we are doing assignment, or are not going to use all of the
114  // LHS domain, we will need to copy the compressed value into the
115  // uncompressed storage. Otherwise, we know we'll just reset all the
116  // values during the upcoming assignment, so it is a waste to do it
117  // now. If the arguments is true, then copy in the compressed value,
118  // if it is false then allocate storage but do not do anything more
119  // now to initialize it.
120  ASSIGNMSG(msg << "No we cannot compress, so make sure we're ");
121  ASSIGNMSG(msg << "uncompressed. Fill domain? " << !(c3&&c2) << endl);
122  lf.Uncompress( !(c3 && c2) );
123  return false;
124 }
125 
126 
128 //
129 // A class with an interface like BrickIterator
130 // that applies the parens operator to some expression of type Expr.
131 // It passes most operations to the 'Child' item, but retrieves values
132 // by applying operator() to the Child or the Child's returned values.
133 // This is used by the version of assign that lets you assign values
134 // to just one component of a Field on the LHS.
135 //
137 
138 template<class Expr>
139 class ParensIterator : public Expr
140 {
141 public:
142  typedef typename Expr::PETE_Return_t PETE_Return_t;
143 
144  ParensIterator( const Expr& e ) : Expr(e) {}
146  {
147  return (*Expr::Child)(Expr::Value.Arg);
148  }
149  PETE_Return_t& offset(int i) const
150  {
151  return Expr::Child.offset(i)(Expr::Value.Arg);
152  }
153  PETE_Return_t& offset(int i, int j) const
154  {
155  return Expr::Child.offset(i,j)(Expr::Value.Arg);
156  }
157  PETE_Return_t& offset(int i, int j, int k) const
158  {
159  return Expr::Child.offset(i,j,k)(Expr::Value.Arg);
160  }
161 
163  {
164  return (*Expr::Child)(Expr::Value.Arg);
165  }
167  {
168  return Expr::Child.offset(i)(Expr::Value.Arg);
169  }
170  PETE_Return_t& offset(int i, int j)
171  {
172  return Expr::Child.offset(i,j)(Expr::Value.Arg);
173  }
174  PETE_Return_t& offset(int i, int j, int k)
175  {
176  return Expr::Child.offset(i,j,k)(Expr::Value.Arg);
177  }
179  {
180  return Expr::Child.unit_offset(i)(Expr::Value.Arg);
181  }
182  PETE_Return_t& unit_offset(int i, int j)
183  {
184  return Expr::Child.unit_offset(i,j)(Expr::Value.Arg);
185  }
186  PETE_Return_t& unit_offset(int i, int j, int k)
187  {
188  return Expr::Child.unit_offset(i,j,k)(Expr::Value.Arg);
189  }
190 
191  void step(unsigned d)
192  {
193  Expr::Child.step(d);
194  }
195  void rewind(unsigned d)
196  {
197  Expr::Child.rewind(d);
198  }
199  int size(unsigned d) const
200  {
201  return Expr::Child.size(d);
202  }
203  int done(unsigned d) const
204  {
205  return Expr::Child.done(d);
206  }
207  int Stride(int d) const
208  {
209  return Expr::Child.Stride(d);
210  }
211 };
212 
213 
215 //
216 // IndexedBareField = expression assignment.
217 //
218 // This is the specialization with ExprTag<true>, meaning the RHS
219 // is an expression, not just a simple IndexedBareField. This version
220 // only works if the LHS and RHS terms all agree in their parallel
221 // layout within guard-cell tolerances. If they do not, it is
222 // an error and IPPL will report it and die.
223 // Since this is for IndexedBareField, extra checks are done to
224 // make sure you only process the relevant domain, and that you keep
225 // track of how you are indexing the values (using plugbase).
226 //
228 
229 template<class T1, unsigned Dim, class RHS, class OP>
230 void
232  bool fillGC)
233 {
235  const_cast<IndexedBareField<T1,Dim,Dim>&>(aa);
236 
237  // debugging output macros. these are only enabled if DEBUG_ASSIGN is
238  // defined.
239  ASSIGNMSG(Inform msg("assign IBF(t)", INFORM_ALL_NODES));
240  ASSIGNMSG(msg << "Computing assignment to IBF[" << aa.getDomain());
241  ASSIGNMSG(msg << "] ..." << endl);
242 
243  // First check to see if any of the terms on the rhs
244  // are the field on the lhs. If so we'll have to make temporaries.
245  int lhs_id = a.getBareField().get_Id();
246  typename RHS::Wrapped& bb = b.PETE_unwrap();
247  bool both_sides = for_each(bb,SameFieldID(lhs_id),PETE_OrCombiner());
248 
249  // Fill guard cells if necessary
250  ASSIGNMSG(msg << "Checking whether to fill GC's on RHS ..." << endl);
251  for_each(bb, FillGCIfNecessary(a.getBareField()), PETE_NullCombiner());
252 
253  // Begin and end iterators for the local fields in the left hand side.
254  typename BareField<T1,Dim>::iterator_if la = a.getBareField().begin_if();
255  typename BareField<T1,Dim>::iterator_if aend = a.getBareField().end_if();
256 
257  // Set the dirty flag indicating this field should have guard cells
258  // filled next time if we are doing deferred GC fills, since
259  // we will be modifying at least one LField of this BareField.
260  // We need to set this here so that our compression checks on each
261  // LField take the dirty flag setting into account.
262  a.getBareField().setDirtyFlag();
263 
264  // Loop over all the local fields of the left hand side.
265 
266  int lfcount=0;
267  bool needFinalCompressCheck = false;
268  while (la != aend)
269  {
270  // The pointer to the current lhs local field.
271  LField<T1,Dim> *lf = (*la).second.get();
272 
273  // If it is on the rhs somewhere, make a copy of it.
274  if ( both_sides ) {
275  lf = new LField<T1,Dim>( *lf );
276  ASSIGNMSG(msg << "For lf " << lfcount << ": making lfield copy.");
277  ASSIGNMSG(msg << endl);
278  }
279 
280  // Find the local domain.
281  // Intersect with the indexes used to see how much we will actually use.
282  NDIndex<Dim> local_domain = a.getDomain().intersect( lf->getOwned() );
283 
284  // If there is something there...
285  if ( ! local_domain.empty() )
286  {
287  // Some typedefs to make the lines shorter...
288  // types for the left hand side, right hand side and
289  // the whole expression.
290  typedef typename LField<T1,Dim>::iterator LHS;
292 
293  // First look and see if the arrays are sufficiently aligned
294  // to do this in one shot.
295  // We do this by trying to do a plugBase and seeing if it worked.
296 
297  ASSIGNMSG(msg << "For lf " << lfcount << ": plugbase on ");
298  ASSIGNMSG(msg << local_domain << endl);
299  if ( for_each(bb,PlugBase<Dim>( local_domain ), PETE_AndCombiner()) )
300  {
301  ASSIGNMSG(msg << "For lf " << lfcount << " with owned domain ");
302  ASSIGNMSG(msg << lf->getOwned() << " assigned intersection ");
303  ASSIGNMSG(msg << local_domain << " : ");
304 
305  if (a.getBareField().compressible() &&
306  TryCompressLHS(*lf,bb,op,local_domain) ) {
307  // Compressed assign.
308  ASSIGNMSG(msg << "compressed assign, changing ");
309  ASSIGNMSG(msg << *(lf->begin()));
310 
311  // Just apply the operator to the single compressed value
312  // on the LHS. If we're here, we know the RHS is compressed
313  // so we can just evaluate it at its first position.
314  PETE_apply(op, *(lf->begin()), for_each(bb,EvalFunctor_0()));
315  ASSIGNMSG(msg << " to " << *(lf->begin()) << endl);
316  } else {
317  // Loop assign.
318  ASSIGNMSG(msg << "loop assign." << endl);
319 
320  // Create the expression object.
321  ExprT expr(lf->begin(local_domain), bb);
322  expr.apply();
323 
324  // Try to compress this LField since we did an uncompressed
325  // assignment, if the user has requested this kind of
326  // check right after computation on the LField. If this
327  // is not selected, then we'll need to do some end-of-loop
328  // compression checks.
330  ASSIGNMSG(msg << "For lf " << lfcount);
331  ASSIGNMSG(msg << ": doing extra post-compute ");
332  ASSIGNMSG(msg << "compression check ..." << endl);
333  lf->TryCompress(a.getBareField().isDirty());
334  } else {
335  needFinalCompressCheck = true;
336  }
337  }
338  }
339  else
340  {
341  ERRORMSG("All Fields in an expression must be aligned. ");
342  ERRORMSG("(Do you have enough guard cells?)" << endl);
343  ERRORMSG("This error occurred while evaluating an expression ");
344  ERRORMSG("for an LField with domain " << lf->getOwned() << endl);
345  Ippl::abort();
346  }
347  }
348 
349  // If we had to make a copy of the current LField,
350  // swap the pointers and delete the old memory.
351  if ( both_sides )
352  {
353  ASSIGNMSG(msg << "For lf " << lfcount << ": swapping lfield data.");
354  ASSIGNMSG(msg << endl);
355  ASSIGNMSG(msg << "For lf " << lfcount << ": at beg, lfield=" << *lf);
356  ASSIGNMSG(msg << endl);
357  (*la).second->swapData( *lf );
358  delete lf;
359  ASSIGNMSG(msg << "For lf " << lfcount << ": at end, lfield=");
360  ASSIGNMSG(msg << *((*la).second) << endl);
361  }
362 
363  ++la;
364  ++lfcount;
365  }
366 
367 
368  // If we are not deferring guard cell fills, and we need to do this
369  // now, fill the guard cells. This will also apply any boundary
370  // conditions after the guards have been updated.
371  if (fillGC) {
372  ASSIGNMSG(msg << "Filling GC's at end if necessary ..." << endl);
373 
374  a.getBareField().fillGuardCellsIfNotDirty();
375 
376  }
377 
378  // Try to compress the result.
379  if (fillGC && needFinalCompressCheck) {
380  ASSIGNMSG(msg << "Trying to compress BareField at end ..." << endl);
381  a.getBareField().Compress(); // tjw added fillGC 12/16/1997
382  }
383 
384  //INCIPPLSTAT(incExpressions);
385  //INCIPPLSTAT(incIBFEqualsExpression);
386 }
387 
388 
390 //
391 // ParensExpression = expression assignment.
392 //
393 // A version of assign() that handles assignment to just a component of
394 // a Field that has been selected via operator(). This version
395 // only works if the LHS and RHS terms all agree in their parallel
396 // layout within guard-cell tolerances. If they do not, it is
397 // an error and IPPL will report it and die. The item having operator()
398 // applied can be a BareField or an IndexedBareField.
399 //
401 
402 template<class A, class RHS, class OP, class Tag, class TP>
403 void
404 assign(PETE_TUTree<OpParens<TP>,A> lhs, RHS wrhs, OP op, Tag,
405  bool fillGC)
406 {
407 
408  // debugging output macros. these are only enabled if DEBUG_ASSIGN is
409  // defined.
410  ASSIGNMSG(Inform msg("assign Parens", INFORM_ALL_NODES));
411  ASSIGNMSG(msg << "Computing assignment to IBF[" << lhs.Child.getDomain());
412  ASSIGNMSG(msg << "](" << lhs.Value.Arg << ") ..." << endl);
413 
414  enum { Dim = A::Dim_u };
415  typedef typename A::return_type T1;
416 
417  typedef typename Expressionize<RHS>::type::Wrapped RHS_Wrapped;
419  RHS_Wrapped & rhs = expr.PETE_unwrap();
420 
421  // Get a reference to the BareField on the left hand side, and the
422  // total domain we are modifying.
423  BareField<T1,Dim>& bare = lhs.Child.getBareField();
424  const NDIndex<Dim> &total_domain = lhs.Child.getDomain();
425 
426  // Fill guard cells if necessary
427  ASSIGNMSG(msg << "Checking whether to fill GC's on RHS ..." << endl);
429 
430  // Begin and end iterators for the local fields in the left hand side.
431  typename BareField<T1,Dim>::iterator_if la = bare.begin_if();
432  typename BareField<T1,Dim>::iterator_if aend = bare.end_if();
433 
434  // Set the dirty flag indicating this field should have guard cells
435  // filled next time if we are doing deferred GC fills.
436  // We need to set this here so that our compression checks on each
437  // LField take the dirty flag setting into account.
438  bare.setDirtyFlag();
439 
440  // Loop over all the local fields of the left hand side.
441 
442  bool needFinalCompressCheck = false;
443  while (la != aend)
444  {
445  // The pointer to the current lhs local field, and the owned domain.
446  LField<T1,Dim> *lf = (*la).second.get();
447  const NDIndex<Dim> &lo = lf->getOwned();
448 
449  // Find the local domain.
450  // Intersect with the indexes used to see how much we will actually use.
451  NDIndex<Dim> local_domain = total_domain.intersect(lo);
452 
453  // If there is something there...
454  if (!local_domain.empty())
455  {
456  // Some typedefs to make the lines shorter...
457  // types for the left hand side, right hand side and
458  // the whole expression.
459  typedef typename LField<T1,Dim>::iterator LA;
460  typedef PETE_TUTree<OpParens<TP>,LA> LHS;
461  typedef BrickExpression<Dim,ParensIterator<LHS>,RHS_Wrapped,OP>
462  ExprT;
463 
464  // First look and see if the arrays are sufficiently aligned
465  // to do this in one shot.
466  // We do this by trying to do a plugBase and seeing if it worked.
467  ASSIGNMSG(msg << "For lf " << lo << ": plugbase on ");
468  ASSIGNMSG(msg << local_domain << endl);
469  if (for_each(rhs, PlugBase<Dim>(local_domain), PETE_AndCombiner()))
470  {
471  // Check and see if the lhs is already compressed, and if so,
472  // if the RHS is compressed as well. If so, then we can
473  // just do a compressed assign to modify the Nth element
474  // of the compressed value.
475  bool c1 = for_each(rhs, IsCompressed(), PETE_AndCombiner());
476  bool c2 = local_domain.containsAllPoints(lo);
477  bool c3 = lf->IsCompressed();
478  if (bare.compressible() && c1 && c2 && c3) {
479  // We can do a compressed assign, and we know the LHS is
480  // already compressed. So we can just assign to the first
481  // value, which will modify the selected element of that
482  // value.
483  ASSIGNMSG(msg << "Compressed assign on ");
484  ASSIGNMSG(msg << local_domain << ", changing "<< *lf->begin());
485  const ParensIterator<LHS> ilhs = LHS(lhs.Value, lf->begin());
486  PETE_apply(op, *ilhs, for_each(rhs, EvalFunctor_0()));
487  ASSIGNMSG(msg << " to " << *lf->begin() << endl);
488 
489  } else {
490  ASSIGNMSG(msg << "Loop assign on " << local_domain << endl);
491 
492  // We must uncompress, and since we will only be writing
493  // to a portion of each element, we must definitely fill
494  // the domain with the compressed value if it is currently
495  // compressed.
496  lf->Uncompress();
497 
498  // Build an object that will carry out the expression.
499  const ParensIterator<LHS> ilhs =
500  LHS(lhs.Value, lf->begin(local_domain));
501  ExprT expr2(ilhs, rhs, op);
502  expr2.apply();
503 
504  // Try to compress this LField right after we've modified it,
505  // if the user wants us to do this now.
507  ASSIGNMSG(msg << "Doing extra post-compute ");
508  ASSIGNMSG(msg << "compression check ..." << endl);
509  lf->TryCompress(bare.isDirty());
510  } else {
511  needFinalCompressCheck = true;
512  }
513  }
514  }
515  else
516  {
517  ERRORMSG("All Fields in an expression must be aligned. ");
518  ERRORMSG("(Do you have enough guard cells?)" << endl);
519  ERRORMSG("This error occurred while evaluating an expression ");
520  ERRORMSG("for an LField with domain ");
521  ERRORMSG((*la).second->getOwned() << endl);
522  Ippl::abort();
523  }
524  }
525  ++la;
526  }
527 
528 
529  // Fill the guard cells on the left hand side, if we are deferring
530  // this operation until the next time it is needed.
531  ASSIGNMSG(msg << "Filling GC's at end if necessary ..." << endl);
532  if (fillGC) {
533 
535 
536  }
537 
538  // Compress the LHS.
539  if (fillGC && needFinalCompressCheck) {
540  ASSIGNMSG(msg << "Trying to compress BareField at end ..." << endl);
541  bare.Compress();
542  }
543 
544  //INCIPPLSTAT(incExpressions);
545  //INCIPPLSTAT(incParensEqualsExpression);
546 }
547 
548 
550 //
551 // BareField = expression assignment.
552 //
553 // This is the specialization with ExprTag<true>, meaning the RHS
554 // is an expression, not just a simple BareField. This version
555 // only works if the LHS and RHS terms all agree in their parallel
556 // layout within guard-cell tolerances. If they do not, it is
557 // an error and IPPL will report it and die.
558 // Since this is for BareField, the entire domain of the LHS is
559 // used to index the RHS. The RHS terms cannot be IndexedBareFields,
560 // they must be BareFields as well (or other simpler items).
561 //
563 
564 template<class T1, unsigned Dim, class RHS, class OP>
565 void
566 assign(const BareField<T1,Dim>& ca, RHS b, OP op, ExprTag<true>)
567 {
568 
569  // debugging output macros. these are only enabled if DEBUG_ASSIGN is
570  // defined.
571  ASSIGNMSG(Inform msg("assign BF(t)", INFORM_ALL_NODES));
572  ASSIGNMSG(msg << "Computing assignment to BF[" << ca.getDomain());
573  ASSIGNMSG(msg << "] ..." << endl);
574 
575  // cast away const here for lhs ... unfortunate but necessary.
576  // Also get the item wrapped within the PETE expression.
577  BareField<T1,Dim>& a = const_cast<BareField<T1,Dim>&>(ca);
578  typename RHS::Wrapped& bb = b.PETE_unwrap();
579 
580  // Create iterators over the LHS's LFields.
581  typedef typename LField<T1,Dim>::iterator It;
583  typename BareField<T1,Dim>::iterator_if la = a.begin_if();
584  typename BareField<T1,Dim>::iterator_if aend = a.end_if();
585 
586  // Set the dirty flag indicating this field should have guard cells
587  // filled next time if we are doing deferred GC fills.
588  // We need to set this here so that our compression checks on each
589  // LField take the dirty flag setting into account.
590  a.setDirtyFlag();
591 
592  // Loop over the LHS LFields, and assign from RHS LFields
593 
594  int lfcount = 0;
595  bool needFinalCompressCheck = false;
596  while (la != aend)
597  {
598  // Get the current LHS and set up the RHS to point to the beginning
599  // of its current LField. This second step is done in lieu of doing
600  // a "plugbase", since it is faster and we know we're dealing with
601  // a whole BareField here, not an indexed BareField.
602  LField<T1,Dim>& lf = *(*la).second;
604 
605  ASSIGNMSG(msg << "For lf " << lfcount << " with domain ");
606  ASSIGNMSG(msg << lf.getOwned() << " : ");
607 
608  // Check to see if we can compress here. If so, we can avoid a lot
609  // of work.
610  if (a.compressible() && TryCompressLHS(lf, bb, op, a.getDomain())) {
611  ASSIGNMSG(msg << "compressed assign, changing " << *lf.begin());
612  PETE_apply(op,*lf.begin(),for_each(bb,EvalFunctor_0()));
613  ASSIGNMSG(msg << " to " << *lf.begin() << endl);
614  } else {
615  ASSIGNMSG(msg << "loop assign." << endl);
616 
617  // Create the expression object.
618  ExprT expr(lf.begin(),bb,op);
619  expr.apply();
620 
621  // Try to compress this LField since we did an uncompressed
622  // assignment, if the user has requested this kind of
623  // check right after computation on the LField. If this kind
624  // of request has not been made, then we'll need to do a compression
625  // check at the end.
627  ASSIGNMSG(msg << "For lf " << lfcount);
628  ASSIGNMSG(msg << ": doing extra post-compute ");
629  ASSIGNMSG(msg << "compression check ..." << endl);
630  lf.TryCompress(a.isDirty());
631  } else {
632  needFinalCompressCheck = true;
633  }
634  }
635 
636  ++la;
638  ++lfcount;
639  }
640 
641 
642  // Fill the guard cells on the left hand side, if we are deferring
643  // this operation until the next time it is needed.
644  ASSIGNMSG(msg << "Filling GC's at end if necessary ..." << endl);
645 
646  a.fillGuardCellsIfNotDirty();
647 
648 
649  // Compress the LHS, if necessary
650  if (needFinalCompressCheck) {
651  ASSIGNMSG(msg << "Trying to compress BareField at end ..." << endl);
652  a.Compress();
653  }
654 
655  // Compress the LHS.
656  //INCIPPLSTAT(incExpressions);
657  //INCIPPLSTAT(incBFEqualsExpression);
658 }
const unsigned Dim
#define ASSIGNMSG(x)
Definition: Assign.h:28
void assign(const IndexedBareField< T1, Dim, Dim > &aa, RHS b, OP op, ExprTag< true >, bool fillGC)
Definition: Assign.hpp:231
bool TryCompressLHS(LField< T, Dim > &lf, A &rhs, Op op, const NDIndex< Dim > &domain)
Definition: Assign.hpp:48
bool for_each(const BareFieldIterator< T, D > &p, SameFieldID s, C)
Definition: AssignDefs.h:30
FillGCIfNecessaryTag< D, T1 > FillGCIfNecessary(const BareField< T1, D > &bf)
Definition: AssignTags.h:126
void PETE_apply(const OpPeriodic< T > &, T &a, const T &b)
Definition: BCond.hpp:353
std::complex< double > a
PETE_Combiner< bool, OpOr > PETE_OrCombiner
Definition: PETE.h:468
PETE_Combiner< bool, OpAnd > PETE_AndCombiner
Definition: PETE.h:467
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define INFORM_ALL_NODES
Definition: Inform.h:39
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
constexpr double e
The value of.
Definition: Physics.h:39
NDIndex< Dim > intersect(const NDIndex< Dim > &) const
bool containsAllPoints(const NDIndex< Dim > &b) const
bool empty() const
void setDirtyFlag()
Definition: BareField.h:117
void fillGuardCellsIfNotDirty() const
Definition: BareField.h:122
bool isDirty() const
Definition: BareField.h:116
iterator_if begin_if()
Definition: BareField.h:100
const NDIndex< Dim > & getDomain() const
Definition: BareField.h:152
ac_id_larray::iterator iterator_if
Definition: BareField.h:92
void Compress() const
Definition: BareField.hpp:991
bool compressible() const
Definition: BareField.h:191
iterator_if end_if()
Definition: BareField.h:101
Definition: LField.h:58
void Compress()
Definition: LField.h:161
bool IsCompressed() const
Definition: LField.h:134
const NDIndex< Dim > & getOwned() const
Definition: LField.h:99
bool TryCompress(bool baseOnPhysicalCells=false)
Definition: LField.hpp:214
const iterator & begin() const
Definition: LField.h:110
void Uncompress(bool fill_domain=true)
Definition: LField.h:172
const NDIndex< Dim > & getDomain() const
Definition: Assign.h:48
PETE_Return_t & offset(int i, int j, int k)
Definition: Assign.hpp:174
void rewind(unsigned d)
Definition: Assign.hpp:195
PETE_Return_t & offset(int i)
Definition: Assign.hpp:166
int size(unsigned d) const
Definition: Assign.hpp:199
PETE_Return_t & offset(int i) const
Definition: Assign.hpp:149
void step(unsigned d)
Definition: Assign.hpp:191
int Stride(int d) const
Definition: Assign.hpp:207
int done(unsigned d) const
Definition: Assign.hpp:203
PETE_Return_t & operator*()
Definition: Assign.hpp:162
PETE_Return_t & offset(int i, int j) const
Definition: Assign.hpp:153
PETE_Return_t & operator*() const
Definition: Assign.hpp:145
PETE_Return_t & offset(int i, int j)
Definition: Assign.hpp:170
Expr::PETE_Return_t PETE_Return_t
Definition: Assign.hpp:142
PETE_Return_t & offset(int i, int j, int k) const
Definition: Assign.hpp:157
PETE_Return_t & unit_offset(int i)
Definition: Assign.hpp:178
ParensIterator(const Expr &e)
Definition: Assign.hpp:144
PETE_Return_t & unit_offset(int i, int j)
Definition: Assign.hpp:182
PETE_Return_t & unit_offset(int i, int j, int k)
Definition: Assign.hpp:186
WrappedExpr & PETE_unwrap()
Definition: PETE.h:81
static type apply(const T &t)
Definition: PETE.h:1089
Definition: Inform.h:42
static bool noFieldCompression
Definition: IpplInfo.h:262
static bool extraCompressChecks
Definition: IpplInfo.h:270
static void abort(const char *=0)
Definition: IpplInfo.cpp:616