00001 // -*- C++ -*- 00002 /*************************************************************************** 00003 * 00004 * The IPPL Framework 00005 * 00006 * This program was prepared by PSI. 00007 * All rights in the program are reserved by PSI. 00008 * Neither PSI nor the author(s) 00009 * makes any warranty, express or implied, or assumes any liability or 00010 * responsibility for the use of this software 00011 * 00012 * Visit http://www.acl.lanl.gov/POOMS for more details 00013 * 00014 ***************************************************************************/ 00015 00016 // -*- C++ -*- 00017 /*************************************************************************** 00018 * 00019 * The IPPL Framework 00020 * 00021 * 00022 * Visit http://people.web.psi.ch/adelmann/ for more details 00023 * 00024 ***************************************************************************/ 00025 00026 // include files 00027 #include "SubField/SubFieldAssign.h" 00028 #include "SubField/SubFieldAssignDefs.h" 00029 #include "SubField/SubBareField.h" 00030 #include "SubField/SubFieldTraits.h" 00031 #include "SubField/SubFieldIter.h" 00032 #include "Field/BareField.h" 00033 #include "Field/BrickExpression.h" 00034 #include "Field/LField.h" 00035 #include "Field/Assign.h" 00036 #include "Field/AssignDefs.h" 00037 #include "Profile/Profiler.h" 00038 #include "Utility/IpplInfo.h" 00039 00040 00042 // assign an arbitrary expression to a SubBareField, with aligned Fields 00043 template<class T1, unsigned Dim, class S, class RHS, class OP> 00044 void assign(SubBareField<T1,Dim,S> a, RHS b, OP op, ExprTag<true>) { 00045 TAU_TYPE_STRING(taustr, "void (" + CT(a) + ", " + CT(b) + ", " + CT(op) 00046 + ", ExprTag<true> )" ); 00047 TAU_PROFILE("assign()", taustr, TAU_SUBFIELD | TAU_ASSIGN); 00048 00049 // Get the object wrapped in the PETE expression object 00050 typename RHS::Wrapped& bb = b.PETE_unwrap(); 00051 00052 // Inform msg("SubField::assign"); 00053 00054 // Check to see if any of the terms on the rhs 00055 // are the field on the lhs. If so we'll have to make temporaries. 00056 int lhs_id = a.getBareField().get_Id(); 00057 bool both_sides = for_each(bb,SameFieldID(lhs_id),PETE_OrCombiner()); 00058 00059 // Check to see if the same type of indexing object is used by all 00060 // the Field's involved in the expression. If any are different, we 00061 // must flag an error. This also checks to make sure that all 00062 // indexed fields have the proper number of brackets. 00063 PInsist(for_each(bb,SameSubsetType(a.getSubsetType()),PETE_AndCombiner()), 00064 "Sparse-Indexed expressions must use consistent indexing."); 00065 00066 // Find the 'bounding box' of the LHS domain 00067 NDIndex<Dim> boundBox; 00068 a.makeNDIndex(boundBox); 00069 00070 // Fill guard cells, if necessary ... this is done if the RHS domains 00071 // represent a stencil, and the guard cells for the corresponding fields 00072 // actually need to be swapped. 00073 //tjw3/3/99 for_each(bb, FillGCIfNecessary(boundBox), PETE_NullCombiner()); 00074 00075 // This weird tag is needed, because using a no-argument FillGCIFNEcessary() 00076 // function didn't work for some reason, at least with some compilers like 00077 // the pre-7.3 SGI compiler and CodeWarrior Pro4. Once the global function 00078 // invocation syntax FillGCIfNecessary<T,D>() is supported by all our 00079 // compilers (it's not there yet in the non-beta SGI compiler), should be 00080 // able to eliminate this FGCINTag business. --tjw 3/3/1999 00081 for_each(bb, FillGCIfNecessary(FGCINTag<Dim,T1>()), PETE_NullCombiner()); 00082 00083 // Iterators for the LHS components and LField's 00084 typename SubBareField<T1,Dim,S>::iterator sba = a.begin(); 00085 typename BareField<T1,Dim>::iterator_if la = sba.getLFieldIter(); 00086 typename BareField<T1,Dim>::iterator_if aend = a.end().getLFieldIter(); 00087 00088 // Do any initial work on the expression it needs before starting. 00089 // E.g., for single-value subsets, this will distribute the values to nodes 00090 sba.initialize(); 00091 for_each(bb, SubsetInit(), PETE_NullCombiner()); 00092 00093 // Loop over all the local fields of the left hand side. 00094 while (la != aend) { 00095 // Some typedefs to make the lines shorter... 00096 // types for the left hand side, right hand side and 00097 // the whole expression. 00098 typedef typename SubBareField<T1,Dim,S>::iterator LHS; 00099 typedef BrickExpression<LHS::ExprDim_u,LHS,typename RHS::Wrapped,OP> ExprT; 00100 00101 // The pointer to the current lhs local field. 00102 // If it is on the rhs somewhere, make a copy of it, and tell the 00103 // subfield iterator about it. 00104 LField<T1,Dim> *lf = (*la).second.get(); 00105 if ( both_sides ) 00106 lf = new LField<T1,Dim>( *lf ); 00107 00108 //msg << " Now doing LField pointer = " << &(*lf); 00109 //msg << ", id = " << lf->getVnode(); 00110 //msg << ", data pointer = " << &(*(lf->getP())); 00111 //msg << endl; 00112 00113 // Find the local domain, if any. To do so, intersect 00114 // with the indexes used to see how much we will actually use. If 00115 // findIntersect returns false, then we know there is nothing to do. 00116 // The domain over which we'll be working (and which will be used 00117 // in BrickExpression) is returned in local_domain. 00118 NDIndex<Dim> local_domain; 00119 if (sba.findIntersection(lf->getOwned(), local_domain)) { 00120 // First look and see if the arrays are sufficiently aligned 00121 // to do this in one shot. 00122 // We do this by trying to do a plugBase and seeing if it worked. 00123 if (for_each(bb,PlugBase<Dim>(local_domain), PETE_AndCombiner())) { 00124 00125 // Check and see if the lhs can be compressed. 00126 if (sba.DomainCompressed() && 00127 for_each(bb, DomainCompressed(), PETE_AndCombiner()) && 00128 a.getBareField().compressible() && 00129 TryCompressLHS(*lf,bb,op,local_domain)) { 00130 00131 // Compressed assign. 00132 PETE_apply(op, *(lf->begin()), for_each(bb,EvalFunctor_0())); 00133 00134 } else { 00135 00136 // Loop assign. 00137 lf->Uncompress(); 00138 sba.setLFieldData(lf, local_domain); 00139 ExprT(sba,bb).apply(); 00140 00141 // Try to compress this LField since we did an uncompressed 00142 // assignment, if the user has requested this kind of 00143 // check right after computation on the LField. 00144 if (IpplInfo::extraCompressChecks) 00145 lf->TryCompress(); 00146 } 00147 } else { 00148 ERRORMSG("All Fields in an expression must be aligned. "); 00149 ERRORMSG("(Do you have enough guard cells?)" << endl); 00150 ERRORMSG("This error occurred while evaluating an SIndex-expression "); 00151 ERRORMSG("for an LField with domain " << lf->getOwned() << endl); 00152 Ippl::abort(); 00153 } 00154 } 00155 00156 // If we had to make a copy of the current LField, 00157 // swap the pointers and delete the old memory. 00158 if (both_sides) { 00159 (*la).second->swapData( *lf ); 00160 delete lf; 00161 } 00162 00163 // move iterators on to the next LField 00164 la = sba.nextLField(); 00165 for_each(bb, SubsetNextLField(), PETE_NullCombiner()); 00166 } 00167 00168 // Fill the guard cells on the left hand side. 00169 a.getBareField().setDirtyFlag(); 00170 a.getBareField().fillGuardCellsIfNotDirty(); 00171 00172 // Compress the LHS, if necessary. 00173 if (!IpplInfo::extraCompressChecks) 00174 a.getBareField().Compress(); 00175 00176 INCIPPLSTAT(incExpressions); 00177 INCIPPLSTAT(incSubEqualsExpression); 00178 } 00179 00180 00181 /*************************************************************************** 00182 * $RCSfile: SubFieldAssign.cpp,v $ $Author: adelmann $ 00183 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $ 00184 * IPPL_VERSION_ID: $Id: SubFieldAssign.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 00185 ***************************************************************************/ 00186