src/Particle/IntCIC.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  *
00007  * Visit http://people.web.psi.ch/adelmann/ for more details
00008  *
00009  ***************************************************************************/
00010 
00011 #ifndef INT_CIC_H
00012 #define INT_CIC_H
00013 
00014 /* IntCIC.h -- Definition of simple class to perform cloud-in-cell
00015    interpolation of data for a single particle to or from a IPPL Field.
00016    This interpolation scheme is also referred to as linear interpolation,
00017    area-weighting (in 2D), or volume-weighting (in 3D).                    */
00018 
00019 // include files
00020 #include "Particle/Interpolator.h"
00021 #include "Field/Field.h"
00022 
00023 
00024 // forward declaration
00025 class IntCIC;
00026 
00027 // specialization of InterpolatorTraits
00028 template <class T, unsigned Dim>
00029 struct InterpolatorTraits<T,Dim,IntCIC> {
00030   typedef CacheDataCIC<T,Dim> Cache_t;
00031 };
00032 
00033 
00034 // IntCICImpl class definition
00035 template <unsigned Dim>
00036 class IntCICImpl : public Interpolator {
00037 
00038 public:
00039   // constructor/destructor
00040   IntCICImpl() {}
00041   ~IntCICImpl() {}
00042 
00043   // gather/scatter functions
00044 
00045   // scatter particle data into Field using particle position and mesh
00046   template <class FT, class M, class C, class PT>
00047   static
00048   void scatter(const FT& pdata, Field<FT,Dim,M,C>& f,
00049                const Vektor<PT,Dim>& ppos, const M& mesh) {
00050     CenteringTag<C> ctag;
00051     Vektor<PT,Dim> gpos, dpos, delta;
00052     NDIndex<Dim> ngp;
00053     CompressedBrickIterator<FT,Dim> fiter;
00054     int lgpoff[Dim];
00055     unsigned int d;
00056     // find nearest grid point for particle position, store in NDIndex obj
00057     ngp = FindNGP(mesh, ppos, ctag);
00058     // get position of ngp
00059     FindPos(gpos, mesh, ngp, ctag);
00060     // get mesh spacings
00061     FindDelta(delta, mesh, ngp, ctag);
00062     // Try to find ngp in local fields and get iterator
00063     fiter = getFieldIter(f,ngp);
00064     // Now we find the offset from ngp to next-lowest grip point (lgp)
00065     for (d=0; d<Dim; ++d) {
00066       if (gpos(d) > ppos(d)) {
00067         lgpoff[d] = -1;                // save the offset
00068         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00069       }
00070       else {
00071         lgpoff[d] = 0;                 // save the offset
00072       }
00073     }
00074     // adjust position of Field iterator to lgp position
00075     fiter.moveBy(lgpoff);
00076     // get distance from ppos to gpos
00077     dpos = ppos - gpos;
00078     // normalize dpos by mesh spacing
00079     dpos /= delta;
00080     // accumulate into local elements
00081     ERRORMSG("IntCIC::scatter: not implemented for Dim>3!!"<<endl);
00082     return;
00083   }
00084 
00085   // scatter particle data into Field using particle position and mesh
00086   // and cache mesh information for reuse
00087   template <class FT, class M, class C, class PT>
00088   static
00089   void scatter(const FT& pdata, Field<FT,Dim,M,C>& f,
00090                const Vektor<PT,Dim>& ppos, const M& mesh,
00091                NDIndex<Dim>& ngp, int lgpoff[Dim], Vektor<PT,Dim>& dpos) {
00092     CenteringTag<C> ctag;
00093     Vektor<PT,Dim> gpos, delta;
00094     CompressedBrickIterator<FT,Dim> fiter;
00095     unsigned int d;
00096     // find nearest grid point for particle position, store in NDIndex obj
00097     ngp = FindNGP(mesh, ppos, ctag);
00098     // get position of ngp
00099     FindPos(gpos, mesh, ngp, ctag);
00100     // get mesh spacings
00101     FindDelta(delta, mesh, ngp, ctag);
00102     // Try to find ngp in local fields and get iterator
00103     fiter = getFieldIter(f,ngp);
00104     // Now we find the offset from ngp to next-lowest grip point (lgp)
00105     for (d=0; d<Dim; ++d) {
00106       if (gpos(d) > ppos(d)) {
00107         lgpoff[d] = -1;                // save the offset
00108         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00109       }
00110       else {
00111         lgpoff[d] = 0;                 // save the offset
00112       }
00113     }
00114     // adjust position of Field iterator to lgp position
00115     fiter.moveBy(lgpoff);
00116     // get distance from ppos to gpos
00117     dpos = ppos - gpos;
00118     // normalize dpos by mesh spacing
00119     dpos /= delta;
00120     // accumulate into local elements
00121     ERRORMSG("IntCIC::scatter: not implemented for Dim>3!!"<<endl);
00122     return;
00123   }
00124 
00125   // scatter particle data into Field using cached mesh information
00126   template <class FT, class M, class C, class PT>
00127   static
00128   void scatter(const FT& pdata, Field<FT,Dim,M,C>& f,
00129                const NDIndex<Dim>& ngp, const int lgpoff[Dim],
00130                const Vektor<PT,Dim>& dpos) {
00131     CompressedBrickIterator<FT,Dim> fiter;
00132     // Try to find ngp in local fields and get iterator
00133     fiter = getFieldIter(f,ngp);
00134     // adjust position of Field iterator to lgp position
00135     fiter.moveBy(lgpoff);
00136     // accumulate into local elements
00137     ERRORMSG("IntCIC::scatter: not implemented for Dim>3!!"<<endl);
00138     return;
00139   }
00140 
00141   // gather particle data from Field using particle position and mesh
00142   template <class FT, class M, class C, class PT>
00143   static
00144   void gather(FT& pdata, const Field<FT,Dim,M,C>& f,
00145               const Vektor<PT,Dim>& ppos, const M& mesh) {
00146     CenteringTag<C> ctag;
00147     Vektor<PT,Dim> gpos, dpos, delta;
00148     NDIndex<Dim> ngp;
00149     CompressedBrickIterator<FT,Dim> fiter;
00150     int lgpoff[Dim];
00151     unsigned int d;
00152     // find nearest grid point for particle position, store in NDIndex obj
00153     ngp = FindNGP(mesh, ppos, ctag);
00154     // get position of ngp
00155     FindPos(gpos, mesh, ngp, ctag);
00156     // get mesh spacings
00157     FindDelta(delta, mesh, ngp, ctag);
00158     // Try to find ngp in local fields and get iterator
00159     fiter = getFieldIter(f,ngp);
00160     // Now we find the offset from ngp to next-lowest grip point (lgp)
00161     for (d=0; d<Dim; ++d) {
00162       if (gpos(d) > ppos(d)) {
00163         lgpoff[d] = -1;                // save the offset
00164         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00165       }
00166       else {
00167         lgpoff[d] = 0;                 // save the offset
00168       }
00169     }
00170     // adjust position of Field iterator to lgp position
00171     fiter.moveBy(lgpoff);
00172     // get distance from ppos to gpos
00173     dpos = ppos - gpos;
00174     // normalize dpos by mesh spacing
00175     dpos /= delta;
00176     // accumulate into particle attrib
00177     ERRORMSG("IntCIC::gather: not implemented for Dim>3!!"<<endl);
00178     return;
00179   }
00180 
00181   // gather particle data from Field using particle position and mesh
00182   // and cache mesh information for reuse
00183   template <class FT, class M, class C, class PT>
00184   static
00185   void gather(FT& pdata, const Field<FT,Dim,M,C>& f,
00186               const Vektor<PT,Dim>& ppos, const M& mesh,
00187               NDIndex<Dim>& ngp, int lgpoff[Dim], Vektor<PT,Dim>& dpos) {
00188     CenteringTag<C> ctag;
00189     Vektor<PT,Dim> gpos, delta;
00190     CompressedBrickIterator<FT,Dim> fiter;
00191     unsigned int d;
00192     // find nearest grid point for particle position, store in NDIndex obj
00193     ngp = FindNGP(mesh, ppos, ctag);
00194     // get position of ngp
00195     FindPos(gpos, mesh, ngp, ctag);
00196     // get mesh spacings
00197     FindDelta(delta, mesh, ngp, ctag);
00198     // Try to find ngp in local fields and get iterator
00199     fiter = getFieldIter(f,ngp);
00200     // Now we find the offset from ngp to next-lowest grip point (lgp)
00201     for (d=0; d<Dim; ++d) {
00202       if (gpos(d) > ppos(d)) {
00203         lgpoff[d] = -1;                // save the offset
00204         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00205       }
00206       else {
00207         lgpoff[d] = 0;                 // save the offset
00208       }
00209     }
00210     // adjust position of Field iterator to lgp position
00211     fiter.moveBy(lgpoff);
00212     // get distance from ppos to gpos
00213     dpos = ppos - gpos;
00214     // normalize dpos by mesh spacing
00215     dpos /= delta;
00216     // accumulate into particle attrib
00217     ERRORMSG("IntCIC::gather: not implemented for Dim>3!!"<<endl);
00218     return;
00219   }
00220 
00221   // gather particle data from Field using cached mesh information
00222   template <class FT, class M, class C, class PT>
00223   static
00224   void gather(FT& pdata, const Field<FT,Dim,M,C>& f,
00225               const NDIndex<Dim>& ngp, const int lgpoff[Dim],
00226               const Vektor<PT,Dim>& dpos) {
00227     CompressedBrickIterator<FT,Dim> fiter;
00228     // Try to find ngp in local fields and get iterator
00229     fiter = getFieldIter(f,ngp);
00230     // adjust position of Field iterator to lgp position
00231     fiter.moveBy(lgpoff);
00232     // accumulate into particle attrib
00233     ERRORMSG("IntCIC::gather: not implemented for Dim>3!!"<<endl);
00234     return;
00235   }
00236 
00237 };
00238 
00239 
00240 template <>
00241 class IntCICImpl<1U> : public Interpolator {
00242 
00243 public:
00244   // constructor/destructor
00245   IntCICImpl() {}
00246   ~IntCICImpl() {}
00247 
00248   // gather/scatter functions
00249 
00250   // scatter particle data into Field using particle position and mesh
00251   template <class FT, class M, class C, class PT>
00252   static
00253   void scatter(const FT& pdata, Field<FT,1U,M,C>& f,
00254                const Vektor<PT,1U>& ppos, const M& mesh) {
00255     CenteringTag<C> ctag;
00256     Vektor<PT,1U> gpos, dpos, delta;
00257     NDIndex<1U> ngp;
00258     CompressedBrickIterator<FT,1U> fiter;
00259     int lgpoff[1U];
00260     unsigned int d;
00261     // find nearest grid point for particle position, store in NDIndex obj
00262     ngp = FindNGP(mesh, ppos, ctag);
00263     // get position of ngp
00264     FindPos(gpos, mesh, ngp, ctag);
00265     // get mesh spacings
00266     FindDelta(delta, mesh, ngp, ctag);
00267     // Try to find ngp in local fields and get iterator
00268     fiter = getFieldIter(f,ngp);
00269     // Now we find the offset from ngp to next-lowest grip point (lgp)
00270     for (d=0; d<1U; ++d) {
00271       if (gpos(d) > ppos(d)) {
00272         lgpoff[d] = -1;                // save the offset
00273         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00274       }
00275       else {
00276         lgpoff[d] = 0;                 // save the offset
00277       }
00278     }
00279     // adjust position of Field iterator to lgp position
00280     fiter.moveBy(lgpoff);
00281     // get distance from ppos to gpos
00282     dpos = ppos - gpos;
00283     // normalize dpos by mesh spacing
00284     dpos /= delta;
00285     // accumulate into local elements
00286     *fiter += (1 - dpos(0)) * pdata;
00287     fiter.offset(1) += dpos(0) * pdata;
00288     return;
00289   }
00290 
00291   // scatter particle data into Field using particle position and mesh
00292   // and cache mesh information for reuse
00293   template <class FT, class M, class C, class PT>
00294   static
00295   void scatter(const FT& pdata, Field<FT,1U,M,C>& f,
00296                const Vektor<PT,1U>& ppos, const M& mesh,
00297                NDIndex<1U>& ngp, int lgpoff[1U], Vektor<PT,1U>& dpos) {
00298     CenteringTag<C> ctag;
00299     Vektor<PT,1U> gpos, delta;
00300     CompressedBrickIterator<FT,1U> fiter;
00301     unsigned int d;
00302     // find nearest grid point for particle position, store in NDIndex obj
00303     ngp = FindNGP(mesh, ppos, ctag);
00304     // get position of ngp
00305     FindPos(gpos, mesh, ngp, ctag);
00306     // get mesh spacings
00307     FindDelta(delta, mesh, ngp, ctag);
00308     // Try to find ngp in local fields and get iterator
00309     fiter = getFieldIter(f,ngp);
00310     // Now we find the offset from ngp to next-lowest grip point (lgp)
00311     for (d=0; d<1U; ++d) {
00312       if (gpos(d) > ppos(d)) {
00313         lgpoff[d] = -1;                // save the offset
00314         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00315       }
00316       else {
00317         lgpoff[d] = 0;                 // save the offset
00318       }
00319     }
00320     // adjust position of Field iterator to lgp position
00321     fiter.moveBy(lgpoff);
00322     // get distance from ppos to gpos
00323     dpos = ppos - gpos;
00324     // normalize dpos by mesh spacing
00325     dpos /= delta;
00326     // accumulate into local elements
00327     *fiter += (1 - dpos(0)) * pdata;
00328     fiter.offset(1) += dpos(0) * pdata;
00329     return;
00330   }
00331 
00332   // scatter particle data into Field using cached mesh information
00333   template <class FT, class M, class C, class PT>
00334   static
00335   void scatter(const FT& pdata, Field<FT,1U,M,C>& f,
00336                const NDIndex<1U>& ngp, const int lgpoff[1U],
00337                const Vektor<PT,1U>& dpos) {
00338     CompressedBrickIterator<FT,1U> fiter;
00339     // Try to find ngp in local fields and get iterator
00340     fiter = getFieldIter(f,ngp);
00341     // adjust position of Field iterator to lgp position
00342     fiter.moveBy(lgpoff);
00343     // accumulate into local elements
00344     *fiter += (1 - dpos(0)) * pdata;
00345     fiter.offset(1) += dpos(0) * pdata;
00346     return;
00347   }
00348 
00349   // gather particle data from Field using particle position and mesh
00350   template <class FT, class M, class C, class PT>
00351   static
00352   void gather(FT& pdata, const Field<FT,1U,M,C>& f,
00353               const Vektor<PT,1U>& ppos, const M& mesh) {
00354     CenteringTag<C> ctag;
00355     Vektor<PT,1U> gpos, dpos, delta;
00356     NDIndex<1U> ngp;
00357     CompressedBrickIterator<FT,1U> fiter;
00358     int lgpoff[1U];
00359     unsigned int d;
00360     // find nearest grid point for particle position, store in NDIndex obj
00361     ngp = FindNGP(mesh, ppos, ctag);
00362     // get position of ngp
00363     FindPos(gpos, mesh, ngp, ctag);
00364     // get mesh spacings
00365     FindDelta(delta, mesh, ngp, ctag);
00366     // Try to find ngp in local fields and get iterator
00367     fiter = getFieldIter(f,ngp);
00368     // Now we find the offset from ngp to next-lowest grip point (lgp)
00369     for (d=0; d<1U; ++d) {
00370       if (gpos(d) > ppos(d)) {
00371         lgpoff[d] = -1;                // save the offset
00372         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00373       }
00374       else {
00375         lgpoff[d] = 0;                 // save the offset
00376       }
00377     }
00378     // adjust position of Field iterator to lgp position
00379     fiter.moveBy(lgpoff);
00380     // get distance from ppos to gpos
00381     dpos = ppos - gpos;
00382     // normalize dpos by mesh spacing
00383     dpos /= delta;
00384     // accumulate into particle attrib
00385     pdata = (1 - dpos(0)) * (*fiter) +
00386             dpos(0)       * fiter.offset(1);
00387     return;
00388   }
00389 
00390   // gather particle data from Field using particle position and mesh
00391   // and cache mesh information for reuse
00392   template <class FT, class M, class C, class PT>
00393   static
00394   void gather(FT& pdata, const Field<FT,1U,M,C>& f,
00395               const Vektor<PT,1U>& ppos, const M& mesh,
00396               NDIndex<1U>& ngp, int lgpoff[1U], Vektor<PT,1U>& dpos) {
00397     CenteringTag<C> ctag;
00398     Vektor<PT,1U> gpos, delta;
00399     CompressedBrickIterator<FT,1U> fiter;
00400     unsigned int d;
00401     // find nearest grid point for particle position, store in NDIndex obj
00402     ngp = FindNGP(mesh, ppos, ctag);
00403     // get position of ngp
00404     FindPos(gpos, mesh, ngp, ctag);
00405     // get mesh spacings
00406     FindDelta(delta, mesh, ngp, ctag);
00407     // Try to find ngp in local fields and get iterator
00408     fiter = getFieldIter(f,ngp);
00409     // Now we find the offset from ngp to next-lowest grip point (lgp)
00410     for (d=0; d<1U; ++d) {
00411       if (gpos(d) > ppos(d)) {
00412         lgpoff[d] = -1;                // save the offset
00413         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00414       }
00415       else {
00416         lgpoff[d] = 0;                 // save the offset
00417       }
00418     }
00419     // adjust position of Field iterator to lgp position
00420     fiter.moveBy(lgpoff);
00421     // get distance from ppos to gpos
00422     dpos = ppos - gpos;
00423     // normalize dpos by mesh spacing
00424     dpos /= delta;
00425     // accumulate into particle attrib
00426     pdata = (1 - dpos(0)) * (*fiter) +
00427             dpos(0)       * fiter.offset(1);
00428     return;
00429   }
00430 
00431   // gather particle data from Field using cached mesh information
00432   template <class FT, class M, class C, class PT>
00433   static
00434   void gather(FT& pdata, const Field<FT,1U,M,C>& f,
00435               const NDIndex<1U>& ngp, const int lgpoff[1U],
00436               const Vektor<PT,1U>& dpos) {
00437     CompressedBrickIterator<FT,1U> fiter;
00438     // Try to find ngp in local fields and get iterator
00439     fiter = getFieldIter(f,ngp);
00440     // adjust position of Field iterator to lgp position
00441     fiter.moveBy(lgpoff);
00442     // accumulate into particle attrib
00443     pdata = (1 - dpos(0)) * (*fiter) +
00444             dpos(0)       * fiter.offset(1);
00445     return;
00446   }
00447 
00448 };
00449 
00450 
00451 template <>
00452 class IntCICImpl<2U> : public Interpolator {
00453 
00454 public:
00455   // constructor/destructor
00456   IntCICImpl() {}
00457   ~IntCICImpl() {}
00458 
00459   // gather/scatter functions
00460 
00461   // scatter particle data into Field using particle position and mesh
00462   template <class FT, class M, class C, class PT>
00463   static
00464   void scatter(const FT& pdata, Field<FT,2U,M,C>& f,
00465                const Vektor<PT,2U>& ppos, const M& mesh) {
00466     CenteringTag<C> ctag;
00467     Vektor<PT,2U> gpos, dpos, delta;
00468     NDIndex<2U> ngp;
00469     CompressedBrickIterator<FT,2U> fiter;
00470     int lgpoff[2U];
00471     unsigned int d;
00472     // find nearest grid point for particle position, store in NDIndex obj
00473     ngp = FindNGP(mesh, ppos, ctag);
00474     // get position of ngp
00475     FindPos(gpos, mesh, ngp, ctag);
00476     // get mesh spacings
00477     FindDelta(delta, mesh, ngp, ctag);
00478     // Try to find ngp in local fields and get iterator
00479     fiter = getFieldIter(f,ngp);
00480     // Now we find the offset from ngp to next-lowest grip point (lgp)
00481     for (d=0; d<2U; ++d) {
00482       if (gpos(d) > ppos(d)) {
00483         lgpoff[d] = -1;                // save the offset
00484         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00485       }
00486       else {
00487         lgpoff[d] = 0;                 // save the offset
00488       }
00489     }
00490     // adjust position of Field iterator to lgp position
00491     fiter.moveBy(lgpoff);
00492     // get distance from ppos to gpos
00493     dpos = ppos - gpos;
00494     // normalize dpos by mesh spacing
00495     dpos /= delta;
00496     // accumulate into local elements
00497     *fiter += (1 - dpos(0)) * (1 - dpos(1)) * pdata;
00498     fiter.offset(1,0) += dpos(0) * (1 - dpos(1)) * pdata;
00499     fiter.offset(0,1) += (1 - dpos(0)) * dpos(1) * pdata;
00500     fiter.offset(1,1) += dpos(0) * dpos(1) * pdata;
00501     return;
00502   }
00503 
00504   // scatter particle data into Field using particle position and mesh
00505   // and cache mesh information for reuse
00506   template <class FT, class M, class C, class PT>
00507   static
00508   void scatter(const FT& pdata, Field<FT,2U,M,C>& f,
00509                const Vektor<PT,2U>& ppos, const M& mesh,
00510                NDIndex<2U>& ngp, int lgpoff[2U], Vektor<PT,2U>& dpos) {
00511     CenteringTag<C> ctag;
00512     Vektor<PT,2U> gpos, delta;
00513     CompressedBrickIterator<FT,2U> fiter;
00514     unsigned int d;
00515     // find nearest grid point for particle position, store in NDIndex obj
00516     ngp = FindNGP(mesh, ppos, ctag);
00517     // get position of ngp
00518     FindPos(gpos, mesh, ngp, ctag);
00519     // get mesh spacings
00520     FindDelta(delta, mesh, ngp, ctag);
00521     // Try to find ngp in local fields and get iterator
00522     fiter = getFieldIter(f,ngp);
00523     // Now we find the offset from ngp to next-lowest grip point (lgp)
00524     for (d=0; d<2U; ++d) {
00525       if (gpos(d) > ppos(d)) {
00526         lgpoff[d] = -1;                // save the offset
00527         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00528       }
00529       else {
00530         lgpoff[d] = 0;                 // save the offset
00531       }
00532     }
00533     // adjust position of Field iterator to lgp position
00534     fiter.moveBy(lgpoff);
00535     // get distance from ppos to gpos
00536     dpos = ppos - gpos;
00537     // normalize dpos by mesh spacing
00538     dpos /= delta;
00539     // accumulate into local elements
00540     *fiter += (1 - dpos(0)) * (1 - dpos(1)) * pdata;
00541     fiter.offset(1,0) += dpos(0) * (1 - dpos(1)) * pdata;
00542     fiter.offset(0,1) += (1 - dpos(0)) * dpos(1) * pdata;
00543     fiter.offset(1,1) += dpos(0) * dpos(1) * pdata;
00544     return;
00545   }
00546 
00547   // scatter particle data into Field using cached mesh information
00548   template <class FT, class M, class C, class PT>
00549   static
00550   void scatter(const FT& pdata, Field<FT,2U,M,C>& f,
00551                const NDIndex<2U>& ngp, const int lgpoff[2U],
00552                const Vektor<PT,2U>& dpos) {
00553     CompressedBrickIterator<FT,2U> fiter;
00554     // Try to find ngp in local fields and get iterator
00555     fiter = getFieldIter(f,ngp);
00556     // adjust position of Field iterator to lgp position
00557     fiter.moveBy(lgpoff);
00558     // accumulate into local elements
00559     *fiter += (1 - dpos(0)) * (1 - dpos(1)) * pdata;
00560     fiter.offset(1,0) += dpos(0) * (1 - dpos(1)) * pdata;
00561     fiter.offset(0,1) += (1 - dpos(0)) * dpos(1) * pdata;
00562     fiter.offset(1,1) += dpos(0) * dpos(1) * pdata;
00563     return;
00564   }
00565 
00566   // gather particle data from Field using particle position and mesh
00567   template <class FT, class M, class C, class PT>
00568   static
00569   void gather(FT& pdata, const Field<FT,2U,M,C>& f,
00570               const Vektor<PT,2U>& ppos, const M& mesh) {
00571     CenteringTag<C> ctag;
00572     Vektor<PT,2U> gpos, dpos, delta;
00573     NDIndex<2U> ngp;
00574     CompressedBrickIterator<FT,2U> fiter;
00575     int lgpoff[2U];
00576     unsigned int d;
00577     // find nearest grid point for particle position, store in NDIndex obj
00578     ngp = FindNGP(mesh, ppos, ctag);
00579     // get position of ngp
00580     FindPos(gpos, mesh, ngp, ctag);
00581     // get mesh spacings
00582     FindDelta(delta, mesh, ngp, ctag);
00583     // Try to find ngp in local fields and get iterator
00584     fiter = getFieldIter(f,ngp);
00585     // Now we find the offset from ngp to next-lowest grip point (lgp)
00586     for (d=0; d<2U; ++d) {
00587       if (gpos(d) > ppos(d)) {
00588         lgpoff[d] = -1;                // save the offset
00589         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00590       }
00591       else {
00592         lgpoff[d] = 0;                 // save the offset
00593       }
00594     }
00595     // adjust position of Field iterator to lgp position
00596     fiter.moveBy(lgpoff);
00597     // get distance from ppos to gpos
00598     dpos = ppos - gpos;
00599     // normalize dpos by mesh spacing
00600     dpos /= delta;
00601     // accumulate into particle attrib
00602     pdata = (1 - dpos(0)) * (1 - dpos(1)) * (*fiter) +
00603             dpos(0)       * (1 - dpos(1)) * fiter.offset(1,0) +
00604             (1 - dpos(0)) * dpos(1)       * fiter.offset(0,1) +
00605             dpos(0)       * dpos(1)       * fiter.offset(1,1);
00606     return;
00607   }
00608 
00609   // gather particle data from Field using particle position and mesh
00610   // and cache mesh information for reuse
00611   template <class FT, class M, class C, class PT>
00612   static
00613   void gather(FT& pdata, const Field<FT,2U,M,C>& f,
00614               const Vektor<PT,2U>& ppos, const M& mesh,
00615               NDIndex<2U>& ngp, int lgpoff[2U], Vektor<PT,2U>& dpos) {
00616     CenteringTag<C> ctag;
00617     Vektor<PT,2U> gpos, delta;
00618     CompressedBrickIterator<FT,2U> fiter;
00619     unsigned int d;
00620     // find nearest grid point for particle position, store in NDIndex obj
00621     ngp = FindNGP(mesh, ppos, ctag);
00622     // get position of ngp
00623     FindPos(gpos, mesh, ngp, ctag);
00624     // get mesh spacings
00625     FindDelta(delta, mesh, ngp, ctag);
00626     // Try to find ngp in local fields and get iterator
00627     fiter = getFieldIter(f,ngp);
00628     // Now we find the offset from ngp to next-lowest grip point (lgp)
00629     for (d=0; d<2U; ++d) {
00630       if (gpos(d) > ppos(d)) {
00631         lgpoff[d] = -1;                // save the offset
00632         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00633       }
00634       else {
00635         lgpoff[d] = 0;                 // save the offset
00636       }
00637     }
00638     // adjust position of Field iterator to lgp position
00639     fiter.moveBy(lgpoff);
00640     // get distance from ppos to gpos
00641     dpos = ppos - gpos;
00642     // normalize dpos by mesh spacing
00643     dpos /= delta;
00644     // accumulate into particle attrib
00645     pdata = (1 - dpos(0)) * (1 - dpos(1)) * (*fiter) +
00646             dpos(0)       * (1 - dpos(1)) * fiter.offset(1,0) +
00647             (1 - dpos(0)) * dpos(1)       * fiter.offset(0,1) +
00648             dpos(0)       * dpos(1)       * fiter.offset(1,1);
00649     return;
00650   }
00651 
00652   // gather particle data from Field using cached mesh information
00653   template <class FT, class M, class C, class PT>
00654   static
00655   void gather(FT& pdata, const Field<FT,2U,M,C>& f,
00656               const NDIndex<2U>& ngp, const int lgpoff[2U],
00657               const Vektor<PT,2U>& dpos) {
00658     CompressedBrickIterator<FT,2U> fiter;
00659     // Try to find ngp in local fields and get iterator
00660     fiter = getFieldIter(f,ngp);
00661     // adjust position of Field iterator to lgp position
00662     fiter.moveBy(lgpoff);
00663     // accumulate into particle attrib
00664     pdata = (1 - dpos(0)) * (1 - dpos(1)) * (*fiter) +
00665             dpos(0)       * (1 - dpos(1)) * fiter.offset(1,0) +
00666             (1 - dpos(0)) * dpos(1)       * fiter.offset(0,1) +
00667             dpos(0)       * dpos(1)       * fiter.offset(1,1);
00668     return;
00669   }
00670 
00671 };
00672 
00673 
00674 template <>
00675 class IntCICImpl<3U> : public Interpolator {
00676 
00677 public:
00678   // constructor/destructor
00679   IntCICImpl() {}
00680   ~IntCICImpl() {}
00681 
00682   // gather/scatter functions
00683 
00684   // scatter particle data into Field using particle position and mesh
00685   template <class FT, class M, class C, class PT>
00686   static
00687   void scatter(const FT& pdata, Field<FT,3U,M,C>& f,
00688                const Vektor<PT,3U>& ppos, const M& mesh) {
00689     CenteringTag<C> ctag;
00690     Vektor<PT,3U> gpos, dpos, delta;
00691     NDIndex<3U> ngp;
00692     CompressedBrickIterator<FT,3U> fiter;
00693     int lgpoff[3U];
00694     unsigned int d;
00695     // find nearest grid point for particle position, store in NDIndex obj
00696     ngp = FindNGP(mesh, ppos, ctag);
00697     // get position of ngp
00698     FindPos(gpos, mesh, ngp, ctag);
00699     // get mesh spacings
00700     FindDelta(delta, mesh, ngp, ctag);
00701     // Try to find ngp in local fields and get iterator
00702     fiter = getFieldIter(f,ngp);
00703     // Now we find the offset from ngp to next-lowest grip point (lgp)
00704     for (d=0; d<3U; ++d) {
00705       if (gpos(d) > ppos(d)) {
00706         lgpoff[d] = -1;                // save the offset
00707         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00708       }
00709       else {
00710         lgpoff[d] = 0;                 // save the offset
00711       }
00712     }
00713     // adjust position of Field iterator to lgp position
00714     fiter.moveBy(lgpoff);
00715     // get distance from ppos to gpos
00716     dpos = ppos - gpos;
00717     // normalize dpos by mesh spacing
00718     dpos /= delta;
00719     // accumulate into local elements
00720     *fiter += (1 - dpos(0)) * (1 - dpos(1)) * (1 - dpos(2)) * pdata;
00721     fiter.offset(1,0,0) += dpos(0) * (1 - dpos(1)) * (1 - dpos(2)) * pdata;
00722     fiter.offset(0,1,0) += (1 - dpos(0)) * dpos(1) * (1 - dpos(2)) * pdata;
00723     fiter.offset(1,1,0) += dpos(0) * dpos(1) * (1 - dpos(2)) * pdata;
00724     fiter.offset(0,0,1) += (1 - dpos(0)) * (1 - dpos(1)) * dpos(2) * pdata;
00725     fiter.offset(1,0,1) += dpos(0) * (1 - dpos(1)) * dpos(2) * pdata;
00726     fiter.offset(0,1,1) += (1 - dpos(0)) * dpos(1) * dpos(2) * pdata;
00727     fiter.offset(1,1,1) += dpos(0) * dpos(1) * dpos(2) * pdata;
00728     return;
00729   }
00730 
00731   // scatter particle data into Field using particle position and mesh
00732   // and cache mesh information for reuse
00733   template <class FT, class M, class C, class PT>
00734   static
00735   void scatter(const FT& pdata, Field<FT,3U,M,C>& f,
00736                const Vektor<PT,3U>& ppos, const M& mesh,
00737                NDIndex<3U>& ngp, int lgpoff[3U], Vektor<PT,3U>& dpos) {
00738     CenteringTag<C> ctag;
00739     Vektor<PT,3U> gpos, delta;
00740     CompressedBrickIterator<FT,3U> fiter;
00741     unsigned int d;
00742     // find nearest grid point for particle position, store in NDIndex obj
00743     ngp = FindNGP(mesh, ppos, ctag);
00744     // get position of ngp
00745     FindPos(gpos, mesh, ngp, ctag);
00746     // get mesh spacings
00747     FindDelta(delta, mesh, ngp, ctag);
00748     // Try to find ngp in local fields and get iterator
00749     fiter = getFieldIter(f,ngp);
00750     // Now we find the offset from ngp to next-lowest grip point (lgp)
00751     for (d=0; d<3U; ++d) {
00752       if (gpos(d) > ppos(d)) {
00753         lgpoff[d] = -1;                // save the offset
00754         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00755       }
00756       else {
00757         lgpoff[d] = 0;                 // save the offset
00758       }
00759     }
00760     // adjust position of Field iterator to lgp position
00761     fiter.moveBy(lgpoff);
00762     // get distance from ppos to gpos
00763     dpos = ppos - gpos;
00764     // normalize dpos by mesh spacing
00765     dpos /= delta;
00766     // accumulate into local elements
00767     *fiter += (1 - dpos(0)) * (1 - dpos(1)) * (1 - dpos(2)) * pdata;
00768     fiter.offset(1,0,0) += dpos(0) * (1 - dpos(1)) * (1 - dpos(2)) * pdata;
00769     fiter.offset(0,1,0) += (1 - dpos(0)) * dpos(1) * (1 - dpos(2)) * pdata;
00770     fiter.offset(1,1,0) += dpos(0) * dpos(1) * (1 - dpos(2)) * pdata;
00771     fiter.offset(0,0,1) += (1 - dpos(0)) * (1 - dpos(1)) * dpos(2) * pdata;
00772     fiter.offset(1,0,1) += dpos(0) * (1 - dpos(1)) * dpos(2) * pdata;
00773     fiter.offset(0,1,1) += (1 - dpos(0)) * dpos(1) * dpos(2) * pdata;
00774     fiter.offset(1,1,1) += dpos(0) * dpos(1) * dpos(2) * pdata;
00775     return;
00776   }
00777 
00778   // scatter particle data into Field using cached mesh information
00779   template <class FT, class M, class C, class PT>
00780   static
00781   void scatter(const FT& pdata, Field<FT,3U,M,C>& f,
00782                const NDIndex<3U>& ngp, const int lgpoff[3U],
00783                const Vektor<PT,3U>& dpos) {
00784     CompressedBrickIterator<FT,3U> fiter;
00785     // Try to find ngp in local fields and get iterator
00786     fiter = getFieldIter(f,ngp);
00787     // adjust position of Field iterator to lgp position
00788     fiter.moveBy(lgpoff);
00789     // accumulate into local elements
00790     *fiter += (1 - dpos(0)) * (1 - dpos(1)) * (1 - dpos(2)) * pdata;
00791     fiter.offset(1,0,0) += dpos(0) * (1 - dpos(1)) * (1 - dpos(2)) * pdata;
00792     fiter.offset(0,1,0) += (1 - dpos(0)) * dpos(1) * (1 - dpos(2)) * pdata;
00793     fiter.offset(1,1,0) += dpos(0) * dpos(1) * (1 - dpos(2)) * pdata;
00794     fiter.offset(0,0,1) += (1 - dpos(0)) * (1 - dpos(1)) * dpos(2) * pdata;
00795     fiter.offset(1,0,1) += dpos(0) * (1 - dpos(1)) * dpos(2) * pdata;
00796     fiter.offset(0,1,1) += (1 - dpos(0)) * dpos(1) * dpos(2) * pdata;
00797     fiter.offset(1,1,1) += dpos(0) * dpos(1) * dpos(2) * pdata;
00798     return;
00799   }
00800 
00801   // gather particle data from Field using particle position and mesh
00802   template <class FT, class M, class C, class PT>
00803   static
00804   void gather(FT& pdata, const Field<FT,3U,M,C>& f,
00805               const Vektor<PT,3U>& ppos, const M& mesh) {
00806     CenteringTag<C> ctag;
00807     Vektor<PT,3U> gpos, dpos, delta;
00808     NDIndex<3U> ngp;
00809     CompressedBrickIterator<FT,3U> fiter;
00810     int lgpoff[3U];
00811     unsigned int d;
00812     // find nearest grid point for particle position, store in NDIndex obj
00813     ngp = FindNGP(mesh, ppos, ctag);
00814     // get position of ngp
00815     FindPos(gpos, mesh, ngp, ctag);
00816     // get mesh spacings
00817     FindDelta(delta, mesh, ngp, ctag);
00818     // Try to find ngp in local fields and get iterator
00819     fiter = getFieldIter(f,ngp);
00820     // Now we find the offset from ngp to next-lowest grip point (lgp)
00821     for (d=0; d<3U; ++d) {
00822       if (gpos(d) > ppos(d)) {
00823         lgpoff[d] = -1;                // save the offset
00824         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00825       }
00826       else {
00827         lgpoff[d] = 0;                 // save the offset
00828       }
00829     }
00830     // adjust position of Field iterator to lgp position
00831     fiter.moveBy(lgpoff);
00832     // get distance from ppos to gpos
00833     dpos = ppos - gpos;
00834     // normalize dpos by mesh spacing
00835     dpos /= delta;
00836     // accumulate into particle attrib
00837     pdata = (1 - dpos(0)) * (1 - dpos(1)) * (1 - dpos(2)) * (*fiter)
00838           + dpos(0)       * (1 - dpos(1)) * (1 - dpos(2)) * fiter.offset(1,0,0)
00839           + (1 - dpos(0)) * dpos(1)       * (1 - dpos(2)) * fiter.offset(0,1,0)
00840           + dpos(0)       * dpos(1)       * (1 - dpos(2)) * fiter.offset(1,1,0)
00841           + (1 - dpos(0)) * (1 - dpos(1)) * dpos(2)       * fiter.offset(0,0,1)
00842           + dpos(0)       * (1 - dpos(1)) * dpos(2)       * fiter.offset(1,0,1)
00843           + (1 - dpos(0)) * dpos(1)       * dpos(2)       * fiter.offset(0,1,1)
00844           + dpos(0)       * dpos(1)       * dpos(2)       * fiter.offset(1,1,1);
00845     return;
00846   }
00847 
00848   // gather particle data from Field using particle position and mesh
00849   // and cache mesh information for reuse
00850   template <class FT, class M, class C, class PT>
00851   static
00852   void gather(FT& pdata, const Field<FT,3U,M,C>& f,
00853               const Vektor<PT,3U>& ppos, const M& mesh,
00854               NDIndex<3U>& ngp, int lgpoff[3U], Vektor<PT,3U>& dpos) {
00855     CenteringTag<C> ctag;
00856     Vektor<PT,3U> gpos, delta;
00857     CompressedBrickIterator<FT,3U> fiter;
00858     unsigned int d;
00859     // find nearest grid point for particle position, store in NDIndex obj
00860     ngp = FindNGP(mesh, ppos, ctag);
00861     // get position of ngp
00862     FindPos(gpos, mesh, ngp, ctag);
00863     // get mesh spacings
00864     FindDelta(delta, mesh, ngp, ctag);
00865     // Try to find ngp in local fields and get iterator
00866     fiter = getFieldIter(f,ngp);
00867     // Now we find the offset from ngp to next-lowest grip point (lgp)
00868     for (d=0; d<3U; ++d) {
00869       if (gpos(d) > ppos(d)) {
00870         lgpoff[d] = -1;                // save the offset
00871         gpos(d) = gpos(d) - delta(d);  // adjust gpos to lgp position
00872       }
00873       else {
00874         lgpoff[d] = 0;                 // save the offset
00875       }
00876     }
00877     // adjust position of Field iterator to lgp position
00878     fiter.moveBy(lgpoff);
00879     // get distance from ppos to gpos
00880     dpos = ppos - gpos;
00881     // normalize dpos by mesh spacing
00882     dpos /= delta;
00883     // accumulate into particle attrib
00884     pdata = (1 - dpos(0)) * (1 - dpos(1)) * (1 - dpos(2)) * (*fiter)
00885           + dpos(0)       * (1 - dpos(1)) * (1 - dpos(2)) * fiter.offset(1,0,0)
00886           + (1 - dpos(0)) * dpos(1)       * (1 - dpos(2)) * fiter.offset(0,1,0)
00887           + dpos(0)       * dpos(1)       * (1 - dpos(2)) * fiter.offset(1,1,0)
00888           + (1 - dpos(0)) * (1 - dpos(1)) * dpos(2)       * fiter.offset(0,0,1)
00889           + dpos(0)       * (1 - dpos(1)) * dpos(2)       * fiter.offset(1,0,1)
00890           + (1 - dpos(0)) * dpos(1)       * dpos(2)       * fiter.offset(0,1,1)
00891           + dpos(0)       * dpos(1)       * dpos(2)       * fiter.offset(1,1,1);
00892     return;
00893   }
00894 
00895   // gather particle data from Field using cached mesh information
00896   template <class FT, class M, class C, class PT>
00897   static
00898   void gather(FT& pdata, const Field<FT,3U,M,C>& f,
00899               const NDIndex<3U>& ngp, const int lgpoff[3U],
00900               const Vektor<PT,3U>& dpos) {
00901     CompressedBrickIterator<FT,3U> fiter;
00902     // Try to find ngp in local fields and get iterator
00903     fiter = getFieldIter(f,ngp);
00904     // adjust position of Field iterator to lgp position
00905     fiter.moveBy(lgpoff);
00906     // accumulate into particle attrib
00907     pdata = (1 - dpos(0)) * (1 - dpos(1)) * (1 - dpos(2)) * (*fiter)
00908           + dpos(0)       * (1 - dpos(1)) * (1 - dpos(2)) * fiter.offset(1,0,0)
00909           + (1 - dpos(0)) * dpos(1)       * (1 - dpos(2)) * fiter.offset(0,1,0)
00910           + dpos(0)       * dpos(1)       * (1 - dpos(2)) * fiter.offset(1,1,0)
00911           + (1 - dpos(0)) * (1 - dpos(1)) * dpos(2)       * fiter.offset(0,0,1)
00912           + dpos(0)       * (1 - dpos(1)) * dpos(2)       * fiter.offset(1,0,1)
00913           + (1 - dpos(0)) * dpos(1)       * dpos(2)       * fiter.offset(0,1,1)
00914           + dpos(0)       * dpos(1)       * dpos(2)       * fiter.offset(1,1,1);
00915     return;
00916   }
00917 
00918 };
00919 
00920 
00921 // IntCIC class -- what the user sees
00922 class IntCIC {
00923 
00924 public:
00925   // constructor/destructor
00926   IntCIC() {}
00927   ~IntCIC() {}
00928 
00929   // gather/scatter functions
00930 
00931   // scatter particle data into Field using particle position and mesh
00932   template <class FT, unsigned Dim, class M, class C, class PT>
00933   static
00934   void scatter(const FT& pdata, Field<FT,Dim,M,C>& f,
00935                const Vektor<PT,Dim>& ppos, const M& mesh) {
00936     IntCICImpl<Dim>::scatter(pdata,f,ppos,mesh);
00937   }
00938 
00939   // scatter particle data into Field using particle position and mesh
00940   // and cache mesh information for reuse
00941   template <class FT, unsigned Dim, class M, class C, class PT>
00942   static
00943   void scatter(const FT& pdata, Field<FT,Dim,M,C>& f,
00944                const Vektor<PT,Dim>& ppos, const M& mesh,
00945                CacheDataCIC<PT,Dim>& cache) {
00946     IntCICImpl<Dim>::scatter(pdata,f,ppos,mesh,cache.Index_m,
00947                              cache.Offset_m,cache.Delta_m);
00948   }
00949 
00950   // scatter particle data into Field using cached mesh information
00951   template <class FT, unsigned Dim, class M, class C, class PT>
00952   static
00953   void scatter(const FT& pdata, Field<FT,Dim,M,C>& f,
00954                const CacheDataCIC<PT,Dim>& cache) {
00955     IntCICImpl<Dim>::scatter(pdata,f,cache.Index_m,
00956                              cache.Offset_m,cache.Delta_m);
00957   }
00958 
00959   // gather particle data from Field using particle position and mesh
00960   template <class FT, unsigned Dim, class M, class C, class PT>
00961   static
00962   void gather(FT& pdata, const Field<FT,Dim,M,C>& f,
00963               const Vektor<PT,Dim>& ppos, const M& mesh) {
00964     IntCICImpl<Dim>::gather(pdata,f,ppos,mesh);
00965   }
00966 
00967   // gather particle data from Field using particle position and mesh
00968   // and cache mesh information for reuse
00969   template <class FT, unsigned Dim, class M, class C, class PT>
00970   static
00971   void gather(FT& pdata, const Field<FT,Dim,M,C>& f,
00972               const Vektor<PT,Dim>& ppos, const M& mesh,
00973               CacheDataCIC<PT,Dim>& cache) {
00974     IntCICImpl<Dim>::gather(pdata,f,ppos,mesh,cache.Index_m,
00975                             cache.Offset_m,cache.Delta_m);
00976   }
00977 
00978   // gather particle data from Field using cached mesh information
00979   template <class FT, unsigned Dim, class M, class C, class PT>
00980   static
00981   void gather(FT& pdata, const Field<FT,Dim,M,C>& f,
00982               const CacheDataCIC<PT,Dim>& cache) {
00983     IntCICImpl<Dim>::gather(pdata,f,cache.Index_m,
00984                             cache.Offset_m,cache.Delta_m);
00985   }
00986 
00987 };
00988 
00989 #endif // INT_CIC_H
00990 
00991 /***************************************************************************
00992  * $RCSfile: IntCIC.h,v $   $Author: adelmann $
00993  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:28 $
00994  * IPPL_VERSION_ID: $Id: IntCIC.h,v 1.1.1.1 2003/01/23 07:40:28 adelmann Exp $ 
00995  ***************************************************************************/
00996 

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