OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
32#include "Field/BareField.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
43template<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
PETE_Combiner< bool, OpOr > PETE_OrCombiner
Definition: PETE.h:468
PETE_Combiner< bool, OpAnd > PETE_AndCombiner
Definition: PETE.h:467
std::complex< double > a
void assign(SubBareField< T1, Dim, S > a, RHS b, OP op, ExprTag< true >)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define PInsist(c, m)
Definition: PAssert.h:120
#define INCIPPLSTAT(stat)
Definition: IpplStats.h:236
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
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
void Uncompress(bool fill_domain=true)
Definition: LField.h:172
const iterator & begin() const
Definition: LField.h:110
Definition: Assign.h:48
static bool extraCompressChecks
Definition: IpplInfo.h:270
static void abort(const char *=0)
Definition: IpplInfo.cpp:616