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