OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
SubFieldAssign.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
29 #include "SubField/SubBareField.h"
31 #include "SubField/SubFieldIter.h"
32 #include "Field/BareField.h"
33 #include "Field/BrickExpression.h"
34 #include "Field/LField.h"
35 #include "Field/Assign.h"
36 #include "Field/AssignDefs.h"
37 
38 #include "Utility/IpplInfo.h"
39 
40 
42 // assign an arbitrary expression to a SubBareField, with aligned Fields
43 template<class T1, unsigned Dim, class S, class RHS, class OP>
45 
46  // Get the object wrapped in the PETE expression object
47  typename RHS::Wrapped& bb = b.PETE_unwrap();
48 
49  // Inform msg("SubField::assign");
50 
51  // Check to see if any of the terms on the rhs
52  // are the field on the lhs. If so we'll have to make temporaries.
53  int lhs_id = a.getBareField().get_Id();
54  bool both_sides = for_each(bb,SameFieldID(lhs_id),PETE_OrCombiner());
55 
56  // Check to see if the same type of indexing object is used by all
57  // the Field's involved in the expression. If any are different, we
58  // must flag an error. This also checks to make sure that all
59  // indexed fields have the proper number of brackets.
60  PInsist(for_each(bb,SameSubsetType(a.getSubsetType()),PETE_AndCombiner()),
61  "Sparse-Indexed expressions must use consistent indexing.");
62 
63  // Find the 'bounding box' of the LHS domain
64  NDIndex<Dim> boundBox;
65  a.makeNDIndex(boundBox);
66 
67  // Fill guard cells, if necessary ... this is done if the RHS domains
68  // represent a stencil, and the guard cells for the corresponding fields
69  // actually need to be swapped.
70  //tjw3/3/99 for_each(bb, FillGCIfNecessary(boundBox), PETE_NullCombiner());
71 
72  // This weird tag is needed, because using a no-argument FillGCIFNEcessary()
73  // function didn't work for some reason, at least with some compilers like
74  // the pre-7.3 SGI compiler and CodeWarrior Pro4. Once the global function
75  // invocation syntax FillGCIfNecessary<T,D>() is supported by all our
76  // compilers (it's not there yet in the non-beta SGI compiler), should be
77  // able to eliminate this FGCINTag business. --tjw 3/3/1999
79 
80  // Iterators for the LHS components and LField's
81  typename SubBareField<T1,Dim,S>::iterator sba = a.begin();
82  typename BareField<T1,Dim>::iterator_if la = sba.getLFieldIter();
83  typename BareField<T1,Dim>::iterator_if aend = a.end().getLFieldIter();
84 
85  // Do any initial work on the expression it needs before starting.
86  // E.g., for single-value subsets, this will distribute the values to nodes
87  sba.initialize();
89 
90  // Loop over all the local fields of the left hand side.
91  while (la != aend) {
92  // Some typedefs to make the lines shorter...
93  // types for the left hand side, right hand side and
94  // the whole expression.
95  typedef typename SubBareField<T1,Dim,S>::iterator LHS;
97 
98  // The pointer to the current lhs local field.
99  // If it is on the rhs somewhere, make a copy of it, and tell the
100  // subfield iterator about it.
101  LField<T1,Dim> *lf = (*la).second.get();
102  if ( both_sides )
103  lf = new LField<T1,Dim>( *lf );
104 
105  //msg << " Now doing LField pointer = " << &(*lf);
106  //msg << ", id = " << lf->getVnode();
107  //msg << ", data pointer = " << &(*(lf->getP()));
108  //msg << endl;
109 
110  // Find the local domain, if any. To do so, intersect
111  // with the indexes used to see how much we will actually use. If
112  // findIntersect returns false, then we know there is nothing to do.
113  // The domain over which we'll be working (and which will be used
114  // in BrickExpression) is returned in local_domain.
115  NDIndex<Dim> local_domain;
116  if (sba.findIntersection(lf->getOwned(), local_domain)) {
117  // First look and see if the arrays are sufficiently aligned
118  // to do this in one shot.
119  // We do this by trying to do a plugBase and seeing if it worked.
120  if (for_each(bb,PlugBase<Dim>(local_domain), PETE_AndCombiner())) {
121 
122  // Check and see if the lhs can be compressed.
123  if (sba.DomainCompressed() &&
125  a.getBareField().compressible() &&
126  TryCompressLHS(*lf,bb,op,local_domain)) {
127 
128  // Compressed assign.
129  PETE_apply(op, *(lf->begin()), for_each(bb,EvalFunctor_0()));
130 
131  } else {
132 
133  // Loop assign.
134  lf->Uncompress();
135  sba.setLFieldData(lf, local_domain);
136  ExprT(sba,bb).apply();
137 
138  // Try to compress this LField since we did an uncompressed
139  // assignment, if the user has requested this kind of
140  // check right after computation on the LField.
142  lf->TryCompress();
143  }
144  } else {
145  ERRORMSG("All Fields in an expression must be aligned. ");
146  ERRORMSG("(Do you have enough guard cells?)" << endl);
147  ERRORMSG("This error occurred while evaluating an SIndex-expression ");
148  ERRORMSG("for an LField with domain " << lf->getOwned() << endl);
149  Ippl::abort();
150  }
151  }
152 
153  // If we had to make a copy of the current LField,
154  // swap the pointers and delete the old memory.
155  if (both_sides) {
156  (*la).second->swapData( *lf );
157  delete lf;
158  }
159 
160  // move iterators on to the next LField
161  la = sba.nextLField();
163  }
164 
165  // Fill the guard cells on the left hand side.
166  a.getBareField().setDirtyFlag();
167  a.getBareField().fillGuardCellsIfNotDirty();
168 
169  // Compress the LHS, if necessary.
171  a.getBareField().Compress();
172 
173  INCIPPLSTAT(incExpressions);
174  INCIPPLSTAT(incSubEqualsExpression);
175 }
176 
177 
178 /***************************************************************************
179  * $RCSfile: SubFieldAssign.cpp,v $ $Author: adelmann $
180  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $
181  * IPPL_VERSION_ID: $Id: SubFieldAssign.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $
182  ***************************************************************************/
183 
bool TryCompressLHS(LField< T, Dim > &, A &, Op, const NDIndex< Dim > &)
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
void assign(SubBareField< T1, Dim, S > a, RHS b, OP op, ExprTag< true >)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define INCIPPLSTAT(stat)
Definition: IpplStats.h:236
#define PInsist(c, m)
Definition: PAssert.h:120
ac_id_larray::iterator iterator_if
Definition: BareField.h:92
Definition: LField.h:58
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
Definition: Assign.h:48
static bool extraCompressChecks
Definition: IpplInfo.h:270
static void abort(const char *=0)
Definition: IpplInfo.cpp:616