src/SubParticle/SubParticleAssign.cpp

Go to the documentation of this file.
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 

Generated on Mon Jan 16 13:23:56 2006 for IPPL by  doxygen 1.4.6