$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

fineGridProcessors2D.hh

Go to the documentation of this file.
00001 /* This file is part of the Palabos library.
00002  *
00003  * Copyright (C) 2011 FlowKit Sarl
00004  * Avenue de Chailly 23
00005  * 1012 Lausanne, Switzerland
00006  * E-mail contact: contact@flowkit.com
00007  *
00008  * The most recent release of Palabos can be downloaded at 
00009  * <http://www.palabos.org/>
00010  *
00011  * The library Palabos is free software: you can redistribute it and/or
00012  * modify it under the terms of the GNU Affero General Public License as
00013  * published by the Free Software Foundation, either version 3 of the
00014  * License, or (at your option) any later version.
00015  *
00016  * The library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Affero General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Affero General Public License
00022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 */
00024 
00025 /* Main author: Daniel Lagrava
00026  */
00027 
00031 #ifndef FINE_GRID_PROCESSORS_2D_HH
00032 #define FINE_GRID_PROCESSORS_2D_HH
00033 
00034 #include <iomanip>
00035 
00036 #include "multiGrid/fineGridProcessors2D.h"
00037 #include "multiBlock/multiDataProcessorWrapper2D.h"
00038 #include "finiteDifference/fdStencils1D.h"
00039 #include "core/geometry2D.h"
00040 
00041 namespace plb {
00042 
00043 /* *************** Class CopyCoarseToFineLinearInterp2D ****************** */
00044 
00045 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00046 CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineLinearInterp2D (
00047         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00048         plint direction_, plint orientation_ )
00049     : rescaleEngine(rescaleEngine_),
00050       direction(direction_), orientation(orientation_)
00051 { }
00052 
00053 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00054 CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>::~CopyCoarseToFineLinearInterp2D() {
00055     delete rescaleEngine;
00056 }
00057 
00058 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00059 CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineLinearInterp2D (
00060         CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00061     : rescaleEngine(rhs.rescaleEngine->clone()),
00062       direction(rhs.direction), orientation(rhs.orientation)
00063 { }
00064 
00065 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00066 CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>&
00067     CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>::operator= (
00068             CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00069 {
00070     delete rescaleEngine;
00071     rescaleEngine = rhs.rescaleEngine->clone();
00072     direction = rhs.direction;
00073     orientation = rhs.orientation;
00074 }
00075 
00076 
00077 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00078     void CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>::process (
00079          Box2D coarseDomain,
00080          BlockLattice2D<T,Descriptor1>& coarseLattice,
00081          BlockLattice2D<T,Descriptor2>& fineLattice )
00082 {
00083     const plint x0 = coarseDomain.x0;
00084     const plint y0 = coarseDomain.y0;
00085     const plint x1 = coarseDomain.x1;
00086     const plint y1 = coarseDomain.y1;
00087     
00088     PLB_PRECONDITION ( x0==x1 || y0==y1 );
00089     
00090     Array<plint,Descriptor1<T>::d> delta;
00091     delta.resetToZero();
00092     if (direction == 0) delta[1]=1; else delta[0]=1;
00093     plint whichTime = 1;
00094 
00095     std::vector<T> pop1;
00096     std::vector<T> pop2;
00097     
00098     CoarseToFineConverter2D<T,Descriptor1,Descriptor2> converter(coarseLattice, fineLattice);
00099 
00100     // Check if the extended domain (over which the interpolation is executed) exceeds either
00101     //   the coarse or the fine lattice, in which case interpolation is not executed in these
00102     //   areas.
00103     Dot2D coarseLeftExcess ( x0 - delta[0], y0 - delta[1] );
00104     Dot2D fineLeftExcess   ( converter.fineX(x0) - delta[0],
00105                              converter.fineY(y0) - delta[1] );
00106     Dot2D coarseRightExcess( x1 + delta[0], y1 + delta[1] );
00107     Dot2D fineRightExcess  ( converter.fineX(x1) + delta[0],
00108                              converter.fineY(y1) + delta[1] );
00109     // leftOutOfRange is true if interpolations are out-of-range on the left side of the domain.
00110     bool leftOutOfRange = ( !contained(coarseLeftExcess, coarseLattice.getBoundingBox()) ||
00111                             !contained(fineLeftExcess, fineLattice.getBoundingBox()) );
00112     // rightOutOfRange is true if interpolations are out-of-range on the right side of the domain.
00113     bool rightOutOfRange = ( !contained(coarseRightExcess, coarseLattice.getBoundingBox()) ||
00114                         !contained(fineRightExcess, fineLattice.getBoundingBox()) );
00115 
00116     // STEP 1: Add left-most cell to the interpolation engine, and perform left-most interpolation
00117     //   unless interpolations are out-of-range on the left side of the domain.
00118     
00119     if (!leftOutOfRange) {
00120         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0-delta[0],y0-delta[1]) , pop1 );
00121         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0,y0)                   , pop2 );
00122         linearInterpolation(pop1,pop2,
00123                             converter.fineDynamics(x0, y0, -delta[0],-delta[1]).getDecomposedValues(whichTime));
00124     }
00125 
00126     // STEP 2: Perform copies and right-directed interpolations on each cell, except the last one
00127     //   (which must be treated individually to avoid out-of-range problems).
00128     
00129     for (plint iX=x0; iX<=x1-delta[0]; ++iX) {
00130         for (plint iY=y0; iY<=y1-delta[1]; ++iY) {
00131             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX,iY)                   , pop1 );
00132             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+delta[0],iY+delta[1]) , pop2 );
00133             converter.fineDynamics(iX,iY, 
00134                                    0,0).getDecomposedValues(whichTime).assign(pop1.begin(),pop1.end());
00135             
00136             // linearInterpolation the unknown population
00137             linearInterpolation(pop1,pop2,
00138                                 converter.fineDynamics(iX,iY, delta[0],delta[1]).getDecomposedValues(whichTime)); 
00139         }
00140     }
00141 
00142     // STEP 3: Copy from the last cell, and perform right-most interpolation unless interpolations
00143     //   are out-of-range on the right side of the domain.
00144     rescaleEngine->scaleCoarseFine( coarseLattice.get(x1,y1)                   , pop1 );
00145     converter.fineDynamics(x1,y1, 0,0).getDecomposedValues(whichTime).assign(pop1.begin(),pop1.end());
00146     
00147     if (!rightOutOfRange) {
00148         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1,y1)                   , pop1 );
00149         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1+delta[0],y1+delta[1]) , pop2 );
00150         linearInterpolation(pop1,pop2,
00151                             converter.fineDynamics(x1,y1, delta[0],delta[1]).getDecomposedValues(whichTime)); 
00152     }
00153 }
00154 
00155 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00156 CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>*
00157     CopyCoarseToFineLinearInterp2D<T,Descriptor1,Descriptor2>::clone() const
00158 {
00159     return new CopyCoarseToFineLinearInterp2D(*this);
00160 }
00161 
00162 
00163 /* *************** Class CopyCoarseToFineBoundaryLinearInterp2D ********** */
00164 
00165 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00166 CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineBoundaryLinearInterp2D (
00167         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00168         plint direction_, plint orientation_, plint whereToInterpolate_)
00169     : rescaleEngine(rescaleEngine_),
00170       direction(direction_),orientation(orientation_),
00171       whereToInterpolate(whereToInterpolate_)
00172 { }
00173 
00174 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00175 CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineBoundaryLinearInterp2D (
00176         CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00177     : rescaleEngine(rhs.rescaleEngine->clone()),
00178       direction(rhs.direction),orientation(rhs.orientation),
00179       whereToInterpolate(rhs.whereToInterpolate)
00180 { }
00181 
00182 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00183 CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>&
00184     CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>::operator= (
00185         CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00186 {
00187     delete rescaleEngine;
00188     rescaleEngine = rhs.rescaleEngine->clone();
00189     direction = rhs.direction;
00190     orientation = rhs.orientation;
00191     whereToInterpolate = rhs.whereToInterpolate;
00192 }
00193 
00194 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00195 CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>::~CopyCoarseToFineBoundaryLinearInterp2D()
00196 {
00197     delete rescaleEngine;
00198 }
00199 
00200 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00201 void CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>::process (
00202          Box2D domain,
00203          BlockLattice2D<T,Descriptor1>& coarseLattice,
00204          BlockLattice2D<T,Descriptor2>& fineLattice )
00205 {
00206     PLB_PRECONDITION( domain.x0 == domain.x1 );
00207     PLB_PRECONDITION( domain.y0 == domain.y1 );
00208     PLB_PRECONDITION( whereToInterpolate==1 || whereToInterpolate==-1 );           
00209 
00210     plint iX = domain.x0;
00211     plint iY = domain.y0;
00212 
00213     Array<plint,Descriptor1<T>::d> delta;
00214     delta.resetToZero();
00215     if (direction == 0) delta[1]=whereToInterpolate; else delta[0]=whereToInterpolate;
00216     plint whichTime = 1;
00217 
00218     std::vector<T> pop1;
00219     std::vector<T> pop2;
00220     CoarseToFineConverter2D<T,Descriptor1,Descriptor2> converter(coarseLattice, fineLattice);
00221 
00222     // Check if the extended domain (over which the interpolation is executed) exceeds either
00223     //   the coarse or the fine lattice, in which case interpolation is not executed.
00224     Dot2D coarseExcess ( iX + delta[0], iY + delta[1] );
00225     Dot2D fineExcess ( converter.fineX(iX) + delta[0],
00226                        converter.fineY(iY) + delta[1] );
00227     bool outOfRange = ( !contained(coarseExcess, coarseLattice.getBoundingBox()) ||
00228                         !contained(fineExcess, fineLattice.getBoundingBox()) );
00229 
00230     // retrieve the values at x0,y0
00231     rescaleEngine->scaleCoarseFine( coarseLattice.get(iX,iY), pop1 );
00232     // copy them to the corresponding fine site
00233     converter.fineDynamics(iX,iY, 
00234                             0,0).getDecomposedValues(whichTime).assign(pop1.begin(),pop1.end());
00235     
00236     // check if we are not out of range
00237     if (!outOfRange) {
00238         // if it is not the case, linearInterpolation
00239         rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+delta[0],iY+delta[1]) , pop2 );
00240         linearInterpolation(pop1,pop2,
00241                             converter.fineDynamics(iX,iY, delta[0],delta[1]).getDecomposedValues(whichTime)); 
00242     }
00243 }
00244 
00245 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00246 CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>*
00247     CopyCoarseToFineBoundaryLinearInterp2D<T,Descriptor1,Descriptor2>::clone() const
00248 {
00249     return new CopyCoarseToFineBoundaryLinearInterp2D(*this);
00250 }
00251 
00252 
00253 /* *************** Class CopyCoarseToFineCubicInterp2D ****************** */
00254 
00255 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00256 CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineCubicInterp2D (
00257         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00258         plint direction_, plint orientation_ )
00259     : rescaleEngine(rescaleEngine_),
00260       direction(direction_), orientation(orientation_)
00261 { }
00262 
00263 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00264 CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>::~CopyCoarseToFineCubicInterp2D() {
00265     delete rescaleEngine;
00266 }
00267 
00268 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00269 CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineCubicInterp2D (
00270         CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00271     : rescaleEngine(rhs.rescaleEngine->clone()),
00272       direction(rhs.direction), orientation(rhs.orientation)
00273 { }
00274 
00275 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00276 CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>&
00277     CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>::operator= (
00278             CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00279 {
00280     delete rescaleEngine;
00281     rescaleEngine = rhs.rescaleEngine->clone();
00282     direction = rhs.direction;
00283     orientation = rhs.orientation;
00284 }
00285 
00286 
00287 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00288 void CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>::process (
00289          Box2D coarseDomain,
00290          BlockLattice2D<T,Descriptor1>& coarseLattice,
00291          BlockLattice2D<T,Descriptor2>& fineLattice )
00292 {
00293     const plint x0 = coarseDomain.x0;
00294     const plint y0 = coarseDomain.y0;
00295     const plint x1 = coarseDomain.x1;
00296     const plint y1 = coarseDomain.y1;
00297 
00298     CoarseToFineConverter2D<T,Descriptor1,Descriptor2> converter(coarseLattice, fineLattice);
00299 
00300     // prepare the delta, keep in mind that it has Palabos BC conventiion
00301     PLB_PRECONDITION ( x0==x1 || y0==y1 );
00302     Array<plint,Descriptor1<T>::d> delta;
00303     delta.resetToZero();
00304     // recomputing the correct delta in the direction of refinement
00305     if (direction == 0) delta[1]=1; else delta[0]=1;
00306     plint whichTime = 1;
00307             
00308     std::vector<T> pop1;// the leftmost
00309     std::vector<T> pop2;// the current
00310     std::vector<T> pop3;// the next
00311     std::vector<T> pop4;// the rightmost
00312     
00313     // Check if the extended domain (over which the interpolation is executed) exceeds either
00314     //   the coarse or the fine lattice, in which case interpolation is not executed in these
00315     //   areas.
00316     Dot2D coarseLeftExcess ( x0 - 2*delta[0], y0 - 2*delta[1] ); // 2 neighbors for the coarse
00317     Dot2D fineLeftExcess   ( converter.fineX(x0) - 2*delta[0],
00318                              converter.fineY(y0) - 2*delta[1] ); // only one for the fine
00319                              
00320     Dot2D coarseRightExcess( x1 + 2*delta[0], y1 + 2*delta[1] );
00321     Dot2D fineRightExcess  ( converter.fineX(x1) + 2*delta[0],
00322                              converter.fineY(y1) + 2*delta[1] );
00323     
00324     // leftOutOfRange is true if interpolations are out-of-range on the left side of the domain.
00325     bool leftOutOfRange = ( !contained(coarseLeftExcess, coarseLattice.getBoundingBox()) ||
00326                             !contained(fineLeftExcess, fineLattice.getBoundingBox()) );
00327     // rightOutOfRange is true if interpolations are out-of-range on the right side of the domain.
00328     bool rightOutOfRange = ( !contained(coarseRightExcess, coarseLattice.getBoundingBox()) ||
00329                         !contained(fineRightExcess, fineLattice.getBoundingBox()) );
00330     
00331     // STEP 1: Check if we need to interpolate left of x0
00332     if (!leftOutOfRange){
00333         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0-2*delta[0],y0-2*delta[1]) , pop1 );
00334         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0-delta[0],y0-delta[1])     , pop2 );
00335         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0,y0) , pop3 );
00336         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0+delta[0],y0+delta[1]) , pop4 );
00337         
00338         cubicCenteredInterpolation(pop1,pop2,pop3,pop4,
00339                                 converter.fineDynamics(x0,y0, -delta[0],-delta[1]).getDecomposedValues(whichTime));
00340     }
00341                         
00342     // STEP 2: Perform copies and right-directed interpolations on each cell, except the last one
00343     //   (which must be treated individually to avoid out-of-range problems).
00344     for (plint iX=x0; iX<=x1-delta[0]; ++iX) {
00345         for (plint iY=y0; iY<=y1-delta[1]; ++iY) {
00346             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX-delta[0],iY-delta[1]) , pop1 );
00347             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX,iY)                   , pop2 );
00348             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+delta[0],iY+delta[1]) , pop3 );
00349             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+2*delta[0],iY+2*delta[1]) , pop4 );
00350             // copy the known value over iX,iY in fine coordinates
00351             converter.fineDynamics(iX,iY, 
00352                                    0,0).getDecomposedValues(whichTime).assign(pop2.begin(),pop2.end());
00353             // linearInterpolation the unknown population
00354             cubicCenteredInterpolation(pop1,pop2,pop3,pop4,
00355                                 converter.fineDynamics(iX,iY, delta[0],delta[1]).getDecomposedValues(whichTime)); 
00356         }
00357     }
00358     // copy over the last site
00359     rescaleEngine->scaleCoarseFine( coarseLattice.get(x1,y1), pop1 );
00360     converter.fineDynamics(x1,y1, 0,0).getDecomposedValues(whichTime).assign(pop1.begin(),pop1.end());
00361     
00362     // STEP 3: Check if we need to interpolate at the rightmost cells
00363     if (!rightOutOfRange){
00364         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1-delta[0],y1-delta[1]),     pop1 );
00365         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1,y1) ,                      pop2 );
00366         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1+delta[0],y1+delta[1])    , pop3 );
00367         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1+2*delta[0],y1+2*delta[1]), pop4 );
00368         
00369         cubicCenteredInterpolation(pop1,pop2,pop3,pop4,
00370                                 converter.fineDynamics(x1,y1,delta[0],delta[1]).getDecomposedValues(whichTime)); 
00371     }
00372 }
00373 
00374 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00375 CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>*
00376     CopyCoarseToFineCubicInterp2D<T,Descriptor1,Descriptor2>::clone() const
00377 {
00378     return new CopyCoarseToFineCubicInterp2D(*this);
00379 }
00380 
00381 /* *************** Class CopyCoarseToFineCubicInterpWithDeconvolution2D ****************** */
00382 
00383 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00384 CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineCubicInterpWithDeconvolution2D (
00385         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00386         plint direction_, plint orientation_ )
00387     : rescaleEngine(rescaleEngine_),
00388       direction(direction_), orientation(orientation_)
00389 { }
00390 
00391 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00392 CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::~CopyCoarseToFineCubicInterpWithDeconvolution2D() {
00393     delete rescaleEngine;
00394 }
00395 
00396 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00397 CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineCubicInterpWithDeconvolution2D (
00398         CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2> const& rhs )
00399     : rescaleEngine(rhs.rescaleEngine->clone()),
00400       direction(rhs.direction), orientation(rhs.orientation)
00401 { }
00402 
00403 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00404 CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>&
00405     CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::operator= (
00406             CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2> const& rhs )
00407 {
00408     delete rescaleEngine;
00409     rescaleEngine = rhs.rescaleEngine->clone();
00410     direction = rhs.direction;
00411     orientation = rhs.orientation;
00412 }
00413 
00414 
00415 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00416 void CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::process (
00417          Box2D coarseDomain,
00418          BlockLattice2D<T,Descriptor1>& coarseLattice,
00419          BlockLattice2D<T,Descriptor2>& fineLattice )
00420 {
00421     const plint x0 = coarseDomain.x0;
00422     const plint y0 = coarseDomain.y0;
00423     const plint x1 = coarseDomain.x1;
00424     const plint y1 = coarseDomain.y1;
00425     
00426         
00427     CoarseToFineConverter2D<T,Descriptor1,Descriptor2> converter(coarseLattice, fineLattice);
00428 
00429     // prepare the delta, keep in mind that it has Palabos BC conventiion
00430     PLB_PRECONDITION ( x0==x1 || y0==y1 );
00431     Array<plint,Descriptor1<T>::d> delta;
00432     delta.resetToZero();
00433     // recomputing the correct delta in the direction of refinement
00434     if (direction == 0) delta[1]=1; else delta[0]=1;
00435     plint whichTime = 1;
00436             
00437     std::vector<T> pop1;// the leftmost
00438     std::vector<T> pop2;// the current
00439     std::vector<T> pop3;// the next
00440     std::vector<T> pop4;// the rightmost
00441     
00442     // Check if the extended domain (over which the interpolation is executed) exceeds either
00443     //   the coarse or the fine lattice, in which case interpolation is not executed in these
00444     //   areas.
00445     Dot2D coarseLeftExcess ( x0 - 2*delta[0], y0 - 2*delta[1] ); // 2 neighbors for the coarse
00446     Dot2D fineLeftExcess   ( converter.fineX(x0) - 2*delta[0],
00447                              converter.fineY(y0) - 2*delta[1] ); // only one for the fine
00448                              
00449     Dot2D coarseRightExcess( x1 + 2*delta[0], y1 + 2*delta[1] );
00450     Dot2D fineRightExcess  ( converter.fineX(x1) + 2*delta[0],
00451                              converter.fineY(y1) + 2*delta[1] );
00452     
00453     // leftOutOfRange is true if interpolations are out-of-range on the left side of the domain.
00454     bool leftOutOfRange = ( !contained(coarseLeftExcess, coarseLattice.getBoundingBox()) ||
00455                             !contained(fineLeftExcess, fineLattice.getBoundingBox()) );
00456     // rightOutOfRange is true if interpolations are out-of-range on the right side of the domain.
00457     bool rightOutOfRange = ( !contained(coarseRightExcess, coarseLattice.getBoundingBox()) ||
00458                         !contained(fineRightExcess, fineLattice.getBoundingBox()) );
00459     
00460     // STEP 1: Check if we need to interpolate left of x0
00461     if (!leftOutOfRange){
00462         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0-2*delta[0],y0-2*delta[1]) , pop1 );
00463         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0-delta[0],y0-delta[1])     , pop2 );
00464         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0,y0) , pop3 );
00465         rescaleEngine->scaleCoarseFine( coarseLattice.get(x0+delta[0],y0+delta[1]) , pop4 );
00466         
00467         cubicCenteredInterpolation(pop1,pop2,pop3,pop4,
00468                                 converter.fineDynamics(x0,y0, -delta[0],-delta[1]).getDecomposedValues(whichTime));
00469         
00470 //         plint fX = converter.fineX(x0) - delta[0] - orientation*(1-delta[0]); 
00471 //         plint fY = converter.fineY(y0) - delta[1] - orientation*(1-delta[1]); 
00472 //         std::vector<T> correction = computeDeconvolutionExtrapolation(fineLattice, fX, fY, delta[0], delta[1]);
00473 //         std::vector<T> original   = converter.fineDynamics(x0,y0,-delta[0],-delta[1]).getDecomposedValues(whichTime);
00474 //         
00475 //         for (pluint iA = 0; iA < original.size(); ++iA) {
00476 //             original[iA] -= correction[iA];
00477 //         }
00478 //         
00479 //         converter.fineDynamics(x0,y0,-delta[0],-delta[1]).getDecomposedValues(whichTime).assign(original.begin(),original.end());
00480     }
00481                         
00482     // STEP 2: Perform copies and right-directed interpolations on each cell, except the last one
00483     //   (which must be treated individually to avoid out-of-range problems).
00484     for (plint iX=x0; iX<=x1-delta[0]; ++iX) {
00485         for (plint iY=y0; iY<=y1-delta[1]; ++iY) {
00486             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX-delta[0],iY-delta[1]) , pop1 );
00487             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX,iY)                   , pop2 );
00488             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+delta[0],iY+delta[1]) , pop3 );
00489             rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+2*delta[0],iY+2*delta[1]) , pop4 );
00490             // copy the known value over iX,iY in fine coordinates
00491             converter.fineDynamics(iX,iY, 
00492                                    0, 0  ).getDecomposedValues(whichTime).assign(pop2.begin(),pop2.end());
00493                                    
00494 //             plint fX = converter.fineX(iX) - orientation*(1-delta[0]); 
00495 //             plint fY = converter.fineY(iY) - orientation*(1-delta[1]); 
00496 //             
00497 //             std::vector<T> correction = computeDeconvolutionExtrapolation(fineLattice, fX, fY, delta[0], delta[1]);
00498 //             std::vector<T> original   = converter.fineDynamics(iX,iY,0,0).getDecomposedValues(whichTime);
00499 //             
00500 //             for (pluint iA = 0; iA < original.size(); ++iA) {
00501 //                 original[iA] -= correction[iA];
00502 //             }
00503 //             converter.fineDynamics(iX,iY,0,0).getDecomposedValues(whichTime).assign(original.begin(),original.end());
00504             
00505             // linearInterpolation the unknown population
00506             cubicCenteredInterpolation(pop1,pop2,pop3,pop4,
00507                                        converter.fineDynamics(iX,iY, delta[0],delta[1]).getDecomposedValues(whichTime)); 
00508             
00509 //             fX +=  delta[0]; fY += delta[1]; 
00510 //             correction = computeDeconvolutionExtrapolation(fineLattice, fX, fY, delta[0], delta[1]);
00511 //             original   = converter.fineDynamics(iX,iY,delta[0],delta[1]).getDecomposedValues(whichTime);
00512 //             
00513 //             for (pluint iA = 0; iA < original.size(); ++iA) {
00514 //                 original[iA] -= correction[iA];
00515 //             }
00516 //             converter.fineDynamics(iX,iY,delta[0],delta[1]).getDecomposedValues(whichTime).assign(original.begin(),original.end());
00517         }
00518     }
00519     // copy over the last site
00520     rescaleEngine->scaleCoarseFine( coarseLattice.get(x1,y1), pop1 );
00521     converter.fineDynamics(x1,y1, 0,0).getDecomposedValues(whichTime).assign(pop1.begin(),pop1.end());
00522     
00523 //     plint fX = converter.fineX(x1) - orientation*(1-delta[0]); 
00524 //     plint fY = converter.fineY(y1) - orientation*(1-delta[1]); 
00525 //     
00526 //     std::vector<T> correction = computeDeconvolutionExtrapolation(fineLattice, fX, fY, delta[0], delta[1]);
00527 //     std::vector<T> original   = converter.fineDynamics(x1,y1,0,0).getDecomposedValues(whichTime);
00528 //     
00529 //     for (pluint iA = 0; iA < original.size(); ++iA) {
00530 //         original[iA] -= correction[iA];
00531 //     }
00532 //     
00533 //     converter.fineDynamics(x1,y1,0,0).getDecomposedValues(whichTime).assign(original.begin(),original.end());
00534     
00535     // STEP 3: Check if we need to interpolate at the rightmost cells
00536     if (!rightOutOfRange){
00537         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1-delta[0],y1-delta[1]),     pop1 );
00538         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1,y1) ,                      pop2 );
00539         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1+delta[0],y1+delta[1])    , pop3 );
00540         rescaleEngine->scaleCoarseFine( coarseLattice.get(x1+2*delta[0],y1+2*delta[1]), pop4 );
00541         
00542         cubicCenteredInterpolation(pop1,pop2,pop3,pop4,
00543                                    converter.fineDynamics(x1,y1,delta[0],delta[1]).getDecomposedValues(whichTime)); 
00544         
00545 //         plint fX = converter.fineX(x1) - orientation*(1-delta[0]); 
00546 //         plint fY = converter.fineY(y1) - orientation*(1-delta[1]); 
00547 //         std::vector<T> correction = computeDeconvolutionExtrapolation(fineLattice, fX, fY, delta[0], delta[1]);
00548 //         std::vector<T> original   = converter.fineDynamics(x1,y1,delta[0],delta[1]).getDecomposedValues(whichTime);
00549 //         
00550 //         for (pluint iA = 0; iA < original.size(); ++iA) {
00551 //             original[iA] -= correction[iA];
00552 //         }
00553 //         converter.fineDynamics(x1,y1,delta[0],delta[1]).getDecomposedValues(whichTime).assign(original.begin(),original.end());
00554     }
00555 }
00556 
00557 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00558 CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>*
00559     CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::clone() const
00560 {
00561     return new CopyCoarseToFineCubicInterpWithDeconvolution2D(*this);
00562 }
00563 
00564 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00565 std::vector<T> CopyCoarseToFineCubicInterpWithDeconvolution2D<T,Descriptor1,Descriptor2>::
00566     computeDeconvolutionExtrapolation(BlockLattice2D<T,Descriptor2> &fineLattice, plint iX, plint iY, plint dx, plint dy) const
00567 {
00568     std::vector<T> currentDecomp;
00569     std::vector<std::vector<T> > filteredDecomp;
00570     
00571     fineLattice.get(iX+dx,iY+dy).getDynamics().decompose(fineLattice.get(iX+dx,iY+dy), currentDecomp, rescaleEngine->getDecompositionOrder());
00572     filteredDecomp.push_back(currentDecomp);
00573     fineLattice.get(iX-dx,iY-dy).getDynamics().decompose(fineLattice.get(iX-dx,iY-dy), currentDecomp, rescaleEngine->getDecompositionOrder());
00574     filteredDecomp.push_back(currentDecomp);
00575     
00576     fineLattice.get(iX,iY).getDynamics().decompose(fineLattice.get(iX,iY), currentDecomp, rescaleEngine->getDecompositionOrder());
00577     
00578     std::vector<T> refDecomp = currentDecomp;
00579     
00580     for (pluint iA = 0; iA < filteredDecomp.size(); ++iA) {
00581         for (pluint iB = 0; iB < filteredDecomp[iA].size(); ++iB) {
00582             currentDecomp[iB] += filteredDecomp[iA][iB];
00583         }
00584     }
00585     
00586     for (pluint iA = 0; iA < refDecomp.size(); ++iA) {
00587         currentDecomp[iA] /= ((T)filteredDecomp.size()+(T)1);
00588         
00589         refDecomp[iA] -= currentDecomp[iA];
00590         refDecomp[iA] *= (T)0.8;
00591     }
00592     
00593     return refDecomp;
00594 }
00595 
00596 
00597 /* *************** Class CopyCoarseToFineBoundaryCubicInterp2D ************* */
00598 
00599 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00600 CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineBoundaryCubicInterp2D (
00601         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00602         plint direction_, plint orientation_, plint whereToInterpolate_)
00603     : rescaleEngine(rescaleEngine_),
00604       direction(direction_),orientation(orientation_),
00605       whereToInterpolate(whereToInterpolate_)
00606 { }
00607 
00608 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00609 CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>::CopyCoarseToFineBoundaryCubicInterp2D (
00610         CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00611     : rescaleEngine(rhs.rescaleEngine->clone()),
00612       direction(rhs.direction),orientation(rhs.orientation),
00613       whereToInterpolate(rhs.whereToInterpolate)
00614 { }
00615 
00616 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00617 CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>&
00618     CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>::operator= (
00619         CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2> const& rhs )
00620 {
00621     delete rescaleEngine;
00622     rescaleEngine = rhs.rescaleEngine->clone();
00623     direction = rhs.direction;
00624     orientation = rhs.orientation;
00625     whereToInterpolate = rhs.whereToInterpolate;
00626 }
00627 
00628 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00629 CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>::~CopyCoarseToFineBoundaryCubicInterp2D()
00630 {
00631     delete rescaleEngine;
00632 }
00633 
00634 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00635 void CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>::process (
00636          Box2D domain,
00637          BlockLattice2D<T,Descriptor1>& coarseLattice,
00638          BlockLattice2D<T,Descriptor2>& fineLattice )
00639 {
00640     PLB_PRECONDITION( domain.x0 == domain.x1 || domain.y0 == domain.y1 );
00641     PLB_PRECONDITION( whereToInterpolate==1 || whereToInterpolate==-1 );           
00642 
00643     plint iX = domain.x0;
00644     plint iY = domain.y0;
00645 
00646     Array<plint,Descriptor1<T>::d> delta;
00647     delta.resetToZero();
00648     if (direction == 0) delta[1]=whereToInterpolate; else delta[0]=whereToInterpolate;
00649     plint whichTime = 1;
00650 
00651     std::vector<T> pop1;
00652     std::vector<T> pop2;
00653     std::vector<T> pop3;
00654     
00655     CoarseToFineConverter2D<T,Descriptor1,Descriptor2> converter(coarseLattice, fineLattice);
00656 
00657     // retrieve the values at x0,y0 and neighbors
00658     rescaleEngine->scaleCoarseFine( coarseLattice.get(iX,iY), pop1 );
00659     rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+delta[0],iY+delta[1]), pop2 );
00660     rescaleEngine->scaleCoarseFine( coarseLattice.get(iX+2*delta[0],iY+2*delta[1]), pop3 );
00661     
00662     // copy (x0,y0) values from coarse to the corresponding fine site
00663     converter.fineDynamics(iX,iY, 
00664                             0,0).getDecomposedValues(whichTime).assign(pop1.begin(),pop1.end());
00665     // cubic decentered interpolation for the fine site next to (x0,y0)
00666     quadraticNonCenteredInterpolation(pop1,pop2,pop3,
00667                                converter.fineDynamics(iX,iY,delta[0],delta[1]).getDecomposedValues(whichTime)); 
00668     
00669 }
00670 
00671 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00672 CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>*
00673     CopyCoarseToFineBoundaryCubicInterp2D<T,Descriptor1,Descriptor2>::clone() const
00674 {
00675     return new CopyCoarseToFineBoundaryCubicInterp2D(*this);
00676 }
00677 
00678 
00679 
00680 /* *************** Class Copy_t1_to_t0_2D *********************************** */
00681 template<typename T, template<typename U> class Descriptor>
00682 Copy_t1_to_t0_2D<T,Descriptor>::Copy_t1_to_t0_2D(plint numTimeSteps_, plint executionTime_)
00683     : numTimeSteps(numTimeSteps_),
00684       executionTime(executionTime_)
00685 { }
00686 
00687 template<typename T, template<typename U> class Descriptor>
00688 void Copy_t1_to_t0_2D<T,Descriptor>::process(Box2D domain, BlockLattice2D<T,Descriptor>& fineLattice)
00689 {
00690     // Determine current relative value of time steps.
00691     size_t relativeTime = fineLattice.getTimeCounter().getTime()%numTimeSteps;
00692     // Execute data processor only if one is at the end of a cycle.
00693     if ((plint)relativeTime==executionTime) {
00694         for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00695             for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00696                 FineGridBoundaryDynamics<T,Descriptor>& fineDynamics =
00697                     dynamic_cast<FineGridBoundaryDynamics<T,Descriptor>&>
00698                         ( fineLattice.get(iX,iY).getDynamics() );
00699                 std::vector<T>& t0 = fineDynamics.getDecomposedValues(0);
00700                 std::vector<T>& t1 = fineDynamics.getDecomposedValues(1);
00701                 t0.assign(t1.begin(), t1.end());
00702                 // complete populations
00703                 //TODO: erase this and create a data processor that executes this only when needed
00704                 fineDynamics.completePopulations(fineLattice.get(iX,iY));
00705             }
00706         }
00707     } 
00708 }
00709 
00710 template<typename T, template<typename U> class Descriptor>
00711 Copy_t1_to_t0_2D<T,Descriptor>* Copy_t1_to_t0_2D<T,Descriptor>::clone() const {
00712     return new Copy_t1_to_t0_2D(*this);
00713 }
00714 
00715 } // namespace plb
00716 
00717 #endif  // FINE_GRID_PROCESSORS_2D_HH
00718