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 "SubParticle/SubParticleAssign.h" 00028 #include "SubParticle/SubParticleAssignDefs.h" 00029 #include "SubParticle/SubParticleAttrib.h" 00030 #include "Particle/ParticleAttrib.h" 00031 #include "Index/SIndex.h" 00032 #include "Index/LSIndex.h" 00033 #include "Field/BrickExpression.h" 00034 #include "Utility/IpplStats.h" 00035 #include "Profile/Profiler.h" 00036 00037 00039 // simple struct used to indicate whether an operation is just an 00040 // assign, or an accumulation 00041 template<class OP> 00042 struct PAIsAssign { enum { assign = 0 }; }; 00043 00044 template<> 00045 struct PAIsAssign<OpAssign> { enum { assign = 1 }; }; 00046 00047 00049 // assign an arbitrary expression to a SubParticleAttrib, with an 00050 // aligned expression. Note that the ParticleAttrib length may change, 00051 // as it will be adjusted to have the same length as the number of local 00052 // points in the SIndex indexing the SubParticleAttrib. 00053 template<class PA, class T, unsigned Dim, class RHS, class OP> 00054 void assign(SubParticleAttrib<PA,T,Dim> a, RHS b, OP op, ExprTag<true>) { 00055 TAU_TYPE_STRING(taustr, "void (" + CT(a) + ", " + CT(b) + ", " + CT(op) 00056 + ", ExprTag<true> )" ); 00057 TAU_PROFILE("assign()", taustr, TAU_SUBFIELD | TAU_ASSIGN); 00058 00059 // Make sure the LHS ParticleAttrib has the proper length. It should 00060 // have the same length as the number of LOCAL sparse index points. 00061 // If it does not, we readjust the length. Note that for accumulations, 00062 // like +=, -=, etc., the size must already be OK. 00063 if (PAIsAssign<OP>::assign == 1) 00064 a.adjustSize(); 00065 else 00066 PInsist(a.getDomain().size() == a.getAttrib().size(), 00067 "ParticleAttrib[SIndex] accumulation with wrong-sized attribute."); 00068 00069 typedef typename RHS::Wrapped Wrapped; 00070 00071 // Get the object wrapped in the PETE expression object 00072 // RHS::Wrapped& bb = b.PETE_unwrap(); 00073 Wrapped& bb = b.PETE_unwrap(); 00074 // Check to see if the same type of indexing object is used by all 00075 // the Field's involved in the expression. If any are different, we 00076 // must flag an error. This also checks to make sure that all 00077 // indexed fields have the proper number of brackets. 00078 PInsist(for_each(bb,SameSubsetType(a.getSubsetType()),PETE_AndCombiner()), 00079 "Sparse-Indexed expressions must use consistent indexing."); 00080 00081 // Find the 'bounding box' of the LHS domain 00082 NDIndex<Dim> boundBox; 00083 a.makeNDIndex(boundBox); 00084 00085 // Fill guard cells, if necessary ... this is done if the RHS domains 00086 // represent a stencil, and the guard cells for the corresponding fields 00087 // actually need to be swapped. 00088 //tjw for_each(bb, FillGCIfNecessary(boundBox), PETE_NullCombiner()); 00089 00090 // This weird tag is needed, because using a no-argument FillGCIFNEcessary() 00091 // function didn't work for some reason, at least with some compilers like 00092 // the pre-7.3 SGI compiler and CodeWarrior Pro4. Once the global function 00093 // invocation syntax FillGCIfNecessary<T,D>() is supported by all our 00094 // compilers (it's not there yet in the non-beta SGI compiler), should be 00095 // able to eliminate this FGCINTag business. --tjw 3/3/1999 00096 for_each(bb, FillGCIfNecessary(FGCINTag<Dim,T>()), PETE_NullCombiner()); 00097 00098 // Iterators for the LHS components and LField's 00099 typename SubParticleAttrib<PA,T,Dim>::iterator sba = a.begin(); 00100 typename SIndex<Dim>::const_iterator_iv la = sba.getLFieldIter(); 00101 typename SIndex<Dim>::const_iterator_iv aend = a.end().getLFieldIter(); 00102 00103 // Do any initial work on the expression it needs before starting. 00104 // E.g., for single-value subsets, this will distribute the values to nodes 00105 sba.initialize(); 00106 for_each(bb, SubsetInit(), PETE_NullCombiner()); 00107 00108 // Loop over all the local fields of the left hand side. 00109 while (la != aend) { 00110 // Some typedefs to make the lines shorter... 00111 // types for the left hand side, right hand side and 00112 // the whole expression. 00113 typedef typename SubParticleAttrib<PA,T,Dim>::iterator LHS; 00114 typedef BrickExpression<1,LHS,typename RHS::Wrapped,OP> ExprT; 00115 00116 // If there are any points in the local SIndex object (for the current 00117 // local vnode, that is), there is some work to do here. 00118 if ((*la)->size() > 0) { 00119 // Now look and see if the RHS arrays are sufficiently aligned. 00120 // We do this by trying to do a plugBase and seeing if it worked. 00121 if (for_each(bb,PlugBase<Dim>((*la)->getDomain()),PETE_AndCombiner())) { 00122 // Loop assign. 00123 ExprT(sba,bb).apply(); 00124 } else { 00125 ERRORMSG("All items in an expression must be aligned. "); 00126 ERRORMSG("(Do you have enough guard cells?)" << endl); 00127 ERRORMSG("This error occurred while evaluating a "); 00128 ERRORMSG("SubParticleAttrib-expression "); 00129 ERRORMSG("for a vnode with domain " << (*la)->getDomain() << endl); 00130 Ippl::abort(); 00131 } 00132 } 00133 00134 // move iterators on to the next LField 00135 la = sba.nextLField(); 00136 for_each(bb, SubsetNextLField(), PETE_NullCombiner()); 00137 } 00138 00139 INCIPPLSTAT(incParticleExpressions); 00140 } 00141 00142 00143 /*************************************************************************** 00144 * $RCSfile: SubParticleAssign.cpp,v $ $Author: adelmann $ 00145 * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:33 $ 00146 * IPPL_VERSION_ID: $Id: SubParticleAssign.cpp,v 1.1.1.1 2003/01/23 07:40:33 adelmann Exp $ 00147 ***************************************************************************/ 00148