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

gridRefinementProcessors3D.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 GRID_REFINEMENT_PROCESSORS_3D_HH
00032 #define GRID_REFINEMENT_PROCESSORS_3D_HH
00033 
00034 #include "multiGrid/gridRefinementProcessors3D.h"
00035 #include "multiBlock/multiDataProcessorWrapper3D.h"
00036 #include "finiteDifference/fdStencils1D.h"
00037 #include "core/geometry3D.h"
00038 
00039 namespace plb {
00040     
00041     
00042 template<typename T, template<typename U> class Descriptor>
00043 void InterpolateOverLineAndExcess (
00044          Box3D domain,
00045          BlockLattice3D<T,Descriptor>& coarseLattice,
00046          BlockLattice3D<T,Descriptor>& fineLattice,
00047          InterpolationEngine2D<T,Descriptor>* interpolationEngine,
00048          RescaleEngine<T,Descriptor>* rescaleEngine,
00049          std::vector<Dot3D>& delta )
00050 {
00051     const plint x0 = domain.x0;
00052     const plint y0 = domain.y0;
00053     const plint z0 = domain.z0;
00054     const plint x1 = domain.x1;
00055     const plint y1 = domain.y1;
00056     const plint z1 = domain.z1;
00057     
00058     plint whichTime = 1;
00059     CoarseToFineConverter3D<T,Descriptor> converter(coarseLattice, fineLattice);
00060 
00061     // delta[0] especifies the direction of the interpolation
00062     // delta[1] especifies the direction perpendicular to the interpolation
00063     // delta[2] is the sum of the other two deltas
00064     delta.push_back(Dot3D(delta[0].x+delta[1].x,delta[0].y+delta[1].y,delta[0].z+delta[1].z));
00065     
00066     // Check if the extended domain (over which the interpolation is executed) exceeds either
00067     //   the coarse or the fine lattice, in which case interpolation is not executed.
00068     Dot3D coarseExcess ( x0 + delta[1].x, y0 + delta[1].y, z0 + delta[1].z );
00069     Dot3D fineExcess   ( converter.fineX(x0) + delta[1].x,
00070                          converter.fineY(y0) + delta[1].y, 
00071                          converter.fineZ(z0) + delta[1].z );
00072     bool outOfRange = ( !contained(coarseExcess, coarseLattice.getBoundingBox()) ||
00073                         !contained(fineExcess, fineLattice.getBoundingBox()) );
00074     
00075     Dot3D startExcess ( x0 - delta[0].x, y0 - delta[0].y, z0 - delta[0].z );
00076     Dot3D startFineExcess ( converter.fineX(x0) - delta[0].x,
00077                             converter.fineY(y0) - delta[0].y, 
00078                             converter.fineZ(z0) - delta[0].z );
00079     bool startOutOfRange = ( !contained(startExcess, coarseLattice.getBoundingBox()) ||
00080                              !contained(startFineExcess, fineLattice.getBoundingBox()) );
00081     Dot3D endExcess ( x1 + delta[0].x, y1 + delta[0].y, z1 + delta[0].z );
00082     Dot3D endFineExcess ( converter.fineX(x1) + delta[0].x,
00083                           converter.fineY(y1) + delta[0].y, 
00084                           converter.fineZ(z1) + delta[0].z );
00085     bool endOutOfRange = ( !contained(endExcess, coarseLattice.getBoundingBox()) ||
00086                            !contained(endFineExcess, fineLattice.getBoundingBox()) );
00087     
00088     if (!startOutOfRange){
00089         interpolationEngine->pushToCouple (
00090         Array<Cell<T,Descriptor>,2>(coarseLattice.get(x0-delta[0].x,
00091                                                       y0-delta[0].y,
00092                                                       z0-delta[0].z),
00093                                         coarseLattice.get(x0,y0,z0)),
00094         *rescaleEngine );
00095     }
00096     
00097     if (outOfRange && !startOutOfRange){
00098         interpolationEngine->pushToCouple();
00099     }
00100     else {
00101         if (!startOutOfRange && !outOfRange){
00102             interpolationEngine->pushToCouple (
00103                 Array<Cell<T,Descriptor>,2>(coarseLattice.get( x0-delta[0].x+delta[1].x,
00104                                                                y0-delta[0].y+delta[1].y,
00105                                                                z0-delta[0].z+delta[1].z ),
00106                                             coarseLattice.get(  x0+delta[1].x,
00107                                                                 y0+delta[1].y,
00108                                                                 z0+delta[1].z)),
00109             *rescaleEngine );
00110             
00111             if (startOutOfRange){
00112                 interpolationEngine->pushToCouple();
00113             }
00114         }
00115     }
00116     
00117     if (!startOutOfRange){
00118         interpolationEngine->copyFrom (
00119                 converter.fineDynamics(x0,y0,z0, 0,0,0).getDecomposedValues(whichTime), 0 );
00120         interpolationEngine->interpolateFromCouple (
00121             converter.fineDynamics( x0,y0,z0,
00122                                     -delta[0].x, -delta[0].y,-delta[0].z).getDecomposedValues(whichTime), 0,1 );
00123     }
00124     
00125     if (!outOfRange){
00126         if (!startOutOfRange){
00127             interpolationEngine->interpolateFromCouple (
00128                 converter.fineDynamics( x0,y0,z0,
00129                                         -delta[0].x+delta[1].x,
00130                                         -delta[0].y+delta[1].y,
00131                                         -delta[0].z+delta[1].z ).getDecomposedValues(whichTime), 0,2 );
00132             interpolationEngine->interpolateFromAll(
00133                 converter.fineDynamics( x0,y0,z0,
00134                                         delta[1].x,delta[1].y,delta[1].z ).getDecomposedValues(whichTime) );
00135         }
00136         else {
00137             interpolationEngine->interpolateFromCouple (
00138                 converter.fineDynamics( x0,y0,z0,
00139                                         delta[1].x,
00140                                         delta[1].y,
00141                                         delta[1].z ).getDecomposedValues(whichTime), 0,1 );
00142         }
00143     }
00144     
00145     
00146     for (plint iX=x0; iX<=x1-delta[0].x; ++iX) {
00147         for (plint iY=y0; iY<=y1-delta[0].y; ++iY){
00148             for (plint iZ=z0; iZ<=z1-delta[0].z; ++iZ){
00149                 interpolationEngine->pushToCouple (
00150                 Array<Cell<T,Descriptor>,2>(coarseLattice.get(iX, iY, iZ),
00151                                              coarseLattice.get(iX+delta[0].x,
00152                                                                iY+delta[0].y,
00153                                                                iZ+delta[0].z)),
00154                 *rescaleEngine );
00155                 
00156                 if (outOfRange){
00157                     interpolationEngine->pushToCouple();
00158                 }
00159                 else {
00160                     interpolationEngine->pushToCouple (
00161                         Array<Cell<T,Descriptor>,2>(coarseLattice.get( iX+delta[1].x,
00162                                                                        iY+delta[1].y,
00163                                                                        iZ+delta[1].z),
00164                                                      coarseLattice.get( iX+delta[2].x,
00165                                                                         iY+delta[2].y,
00166                                                                         iZ+delta[2].z)),
00167                     *rescaleEngine );
00168                 }
00169                 
00170                 interpolationEngine->copyFrom (
00171                     converter.fineDynamics(iX,iY,iZ, 0,0,0).getDecomposedValues(whichTime), 0 );
00172                 interpolationEngine->copyFrom (
00173                     converter.fineDynamics(iX,iY,iZ,
00174                                            2*delta[0].x,2*delta[0].y,2*delta[0].z).getDecomposedValues(whichTime), 1 );
00175                 interpolationEngine->interpolateFromCouple (
00176                         converter.fineDynamics(iX,iY,iZ,
00177                                                delta[0].x, delta[0].y,delta[0].z).getDecomposedValues(whichTime), 0,1 );
00178                 if (!outOfRange){
00179                     interpolationEngine->interpolateFromCouple (
00180                         converter.fineDynamics( iX,iY,iZ, 
00181                                             delta[1].x, delta[1].y, delta[1].z ).getDecomposedValues(whichTime), 0,2 );
00182                     interpolationEngine->interpolateFromAll(
00183                         converter.fineDynamics( iX,iY,iZ, 
00184                                                delta[2].x,delta[2].y,delta[2].z ).getDecomposedValues(whichTime) );
00185                 }
00186             }
00187         }
00188     }
00189     
00190     
00191     if (!endOutOfRange){
00192         interpolationEngine->pushToCouple (
00193         Array<Cell<T,Descriptor>,2>(coarseLattice.get(x1,y1,z1),
00194                                     coarseLattice.get(x1+delta[0].x,
00195                                                       y1+delta[0].y,
00196                                                       z1+delta[0].z)),
00197         *rescaleEngine );
00198     }
00199     
00200     if (outOfRange && !endOutOfRange){
00201         interpolationEngine->pushToCouple();
00202     }
00203     else {
00204         if (!endOutOfRange && !outOfRange){
00205             interpolationEngine->pushToCouple (
00206                 Array<Cell<T,Descriptor>,2>(coarseLattice.get(  x1+delta[1].x,
00207                                                                 y1+delta[1].y,
00208                                                                 z1+delta[1].z),
00209                                             coarseLattice.get( x1+delta[0].x+delta[1].x,
00210                                                                y1+delta[0].y+delta[1].y,
00211                                                                z1+delta[0].z+delta[1].z )
00212                                             ),
00213             *rescaleEngine );
00214             
00215             if (endOutOfRange){
00216                 interpolationEngine->pushToCouple();
00217             }
00218         }
00219     }
00220     
00221     if (!endOutOfRange){
00222         interpolationEngine->copyFrom (
00223                 converter.fineDynamics(x1,y1,z1, 0,0,0).getDecomposedValues(whichTime), 0 );
00224         interpolationEngine->interpolateFromCouple (
00225             converter.fineDynamics( x1,y1,z1,
00226                                     delta[0].x, delta[0].y,delta[0].z).getDecomposedValues(whichTime), 0,1 );
00227     }
00228     
00229     if (!outOfRange){
00230         if (!endOutOfRange){
00231             interpolationEngine->interpolateFromCouple (
00232                 converter.fineDynamics( x1,y1,z1,
00233                                         delta[1].x,
00234                                         delta[1].y,
00235                                         delta[1].z ).getDecomposedValues(whichTime), 0,2 );
00236             interpolationEngine->interpolateFromAll(
00237                 converter.fineDynamics( x1,y1,z1,
00238                                         delta[2].x,delta[2].y,delta[2].z ).getDecomposedValues(whichTime) );
00239         }
00240         else {
00241             interpolationEngine->interpolateFromCouple (
00242                 converter.fineDynamics( x1,y1,z1,
00243                                         delta[1].x,
00244                                         delta[1].y,
00245                                         delta[1].z ).getDecomposedValues(whichTime), 0,1 );
00246         }
00247     }
00248     
00249     delete rescaleEngine;
00250     delete interpolationEngine;
00251     
00252 }
00253 
00254     
00255 std::vector<Box3D> createCorners(Box3D domain, plint direction){
00256     std::vector<Box3D> result;
00257     if (direction == 0){ // the YZ plane
00258         result.push_back(Box3D(domain.x0,domain.x1,domain.y0,domain.y0,domain.z1,domain.z1)); // CUL
00259         result.push_back(Box3D(domain.x0,domain.x1,domain.y0,domain.y0,domain.z0,domain.z0)); // CLL
00260         result.push_back(Box3D(domain.x0,domain.x1,domain.y1,domain.y1,domain.z0,domain.z0)); // CLR
00261         result.push_back(Box3D(domain.x0,domain.x1,domain.y1,domain.y1,domain.z1,domain.z1)); // CUR
00262     }
00263     if (direction == 1){ // the XZ plane
00264         result.push_back(Box3D(domain.x0,domain.x0,domain.y0,domain.y1,domain.z1,domain.z1));
00265         result.push_back(Box3D(domain.x0,domain.x0,domain.y0,domain.y1,domain.z0,domain.z0));
00266         result.push_back(Box3D(domain.x1,domain.x1,domain.y0,domain.y1,domain.z0,domain.z0));
00267         result.push_back(Box3D(domain.x1,domain.x1,domain.y0,domain.y1,domain.z1,domain.z1));
00268     }
00269     if (direction == 2){ // the XY plane
00270         result.push_back(Box3D(domain.x0,domain.x0,domain.y1,domain.y1,domain.z0,domain.z1));
00271         result.push_back(Box3D(domain.x0,domain.x0,domain.y0,domain.y0,domain.z0,domain.z1));
00272         result.push_back(Box3D(domain.x1,domain.x1,domain.y0,domain.y0,domain.z0,domain.z1));
00273         result.push_back(Box3D(domain.x1,domain.x1,domain.y1,domain.y1,domain.z0,domain.z1));
00274     }
00275     
00276     return result;
00277 }
00278 
00279 Box3D createLeftDomain(Box3D originalDomain, plint direction){
00280     Box3D result;
00281     if (direction == 0){ // the YZ plane
00282         result = Box3D(originalDomain.x0,originalDomain.x1,
00283                        originalDomain.y0,originalDomain.y0,
00284                        originalDomain.z0,originalDomain.z1);
00285     }
00286     if (direction == 1){ // the XZ plane
00287         result = Box3D(originalDomain.x0,originalDomain.x0,
00288                        originalDomain.y0,originalDomain.y1,
00289                        originalDomain.z0,originalDomain.z1);
00290     }
00291     if (direction == 2){ // the XY plane
00292         result = Box3D(originalDomain.x0,originalDomain.x0,
00293                        originalDomain.y0,originalDomain.y1,
00294                        originalDomain.z0,originalDomain.z1);
00295     }
00296     return result;
00297 }
00298 
00299 Box3D createRightDomain(Box3D originalDomain, plint direction){
00300     Box3D result;
00301     if (direction == 0){ // the YZ plane
00302         result = Box3D(originalDomain.x0,originalDomain.x1,
00303                        originalDomain.y1,originalDomain.y1,
00304                        originalDomain.z0,originalDomain.z1);
00305     }
00306     if (direction == 1){ // the XZ plane
00307         result = Box3D(originalDomain.x1,originalDomain.x1,
00308                        originalDomain.y0,originalDomain.y1,
00309                        originalDomain.z0,originalDomain.z1);
00310     }
00311     if (direction == 2){ // the XY plane
00312         result = Box3D(originalDomain.x1,originalDomain.x1,
00313                        originalDomain.y0,originalDomain.y1,
00314                        originalDomain.z0,originalDomain.z1);
00315     }
00316     return result;
00317 }
00318 
00319 Box3D createBottomDomain(Box3D originalDomain, plint direction){
00320     Box3D result;
00321     if (direction == 0){ // the YZ plane
00322         result = Box3D(originalDomain.x0,originalDomain.x1,
00323                        originalDomain.y0,originalDomain.y1,
00324                        originalDomain.z0,originalDomain.z0);
00325     }
00326     if (direction == 1){ // the XZ plane
00327         result = Box3D(originalDomain.x0,originalDomain.x1,
00328                        originalDomain.y0,originalDomain.y1,
00329                        originalDomain.z0,originalDomain.z0);
00330     }
00331     if (direction == 2){ // the XY plane
00332         result = Box3D(originalDomain.x0,originalDomain.x1,
00333                        originalDomain.y0,originalDomain.y0,
00334                        originalDomain.z0,originalDomain.z1);
00335     }
00336     return result;
00337 }
00338 
00339 Box3D createTopDomain(Box3D originalDomain, plint direction){
00340     Box3D result;
00341     if (direction == 0){ // the YZ plane
00342         result = Box3D(originalDomain.x0,originalDomain.x1,
00343                        originalDomain.y0,originalDomain.y1,
00344                        originalDomain.z1,originalDomain.z1);
00345     }
00346     if (direction == 1){ // the XZ plane
00347         result = Box3D(originalDomain.x0,originalDomain.x1,
00348                        originalDomain.y0,originalDomain.y1,
00349                        originalDomain.z1,originalDomain.z1);
00350     }
00351     if (direction == 2){ // the XY plane
00352         result = Box3D(originalDomain.x0,originalDomain.x1,
00353                        originalDomain.y1,originalDomain.y1,
00354                        originalDomain.z0,originalDomain.z1);
00355     }
00356     return result;
00357 }
00358 
00359 
00360 
00361     
00362 /* *************** Class InterpolateCoarseToFineDynamics3D ****************** */
00363 
00364 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00365 InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>::InterpolateCoarseToFineDynamics3D (
00366         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00367         InterpolationEngine2D<T,Descriptor1>* interpolationEngine_,
00368         plint direction_, const Dot3D delta_[2] )
00369     : rescaleEngine(rescaleEngine_),
00370       interpolationEngine(interpolationEngine_),
00371       direction(direction_)
00372 {
00373     delta.push_back(delta_[0]);
00374     delta.push_back(delta_[1]);
00375 }
00376 
00377 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00378 InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>::~InterpolateCoarseToFineDynamics3D() {
00379     delete rescaleEngine;
00380     delete interpolationEngine;
00381 }
00382 
00383 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00384 InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>::InterpolateCoarseToFineDynamics3D (
00385         InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2> const& rhs )
00386     : rescaleEngine(rhs.rescaleEngine->clone()),
00387       interpolationEngine(rhs.interpolationEngine->clone()),
00388       direction(rhs.direction), delta(rhs.delta)
00389 { }
00390 
00391 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00392 InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>&
00393     InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>::operator= (
00394             InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2> const& rhs )
00395 {
00396     delete rescaleEngine;
00397     rescaleEngine = rhs.rescaleEngine->clone();
00398     delete interpolationEngine;
00399     interpolationEngine = rhs.interpolationEngine->clone();
00400     direction = rhs.direction;
00401     delta.assign(rhs.delta.begin(),rhs.delta.end());
00402 }
00403 
00404 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00405     void InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>::process (
00406          Box3D coarseDomain,
00407          BlockLattice3D<T,Descriptor1>& coarseLattice,
00408          BlockLattice3D<T,Descriptor2>& fineLattice )
00409 {
00410     const plint x0 = coarseDomain.x0;
00411     const plint y0 = coarseDomain.y0;
00412     const plint z0 = coarseDomain.z0;
00413     const plint x1 = coarseDomain.x1;
00414     const plint y1 = coarseDomain.y1;
00415     const plint z1 = coarseDomain.z1;
00416     
00417     PLB_PRECONDITION ( x0==x1 || y0==y1 || z0==z1 );
00418     PLB_PRECONDITION ( delta[0].x+delta[0].y+delta[0].z==1 && delta[1].x+delta[1].y+delta[1].z==1 );
00419     // creation of delta[2]
00420     delta.push_back(Dot3D(delta[0].x+delta[1].x,delta[0].y+delta[1].y,delta[0].z+delta[1].z));
00421  
00422     CoarseToFineConverter3D<T,Descriptor1> converter(coarseLattice, fineLattice);
00423     plint whichTime=1;
00424 
00425     // Check if the extended domain (over which the interpolation is executed) exceeds either
00426     //   the coarse or the fine lattice, in which case interpolation is not executed in these
00427     //   areas.
00428     Dot3D coarseLeftExcess ( x0 - delta[0].x, y0 - delta[0].y, z0 - delta[0].z );
00429     Dot3D fineLeftExcess   ( converter.fineX(x0) - delta[0].x,
00430                              converter.fineY(y0) - delta[0].y, 
00431                              converter.fineZ(z0) - delta[0].z );
00432     Dot3D coarseRightExcess( x1 + delta[0].x, y1 + delta[0].y, z1 + delta[0].z );
00433     Dot3D fineRightExcess  ( converter.fineX(x1) + delta[0].x,
00434                              converter.fineY(y1) + delta[0].y,
00435                              converter.fineZ(z1) + delta[0].z );
00436     Dot3D coarseBottomExcess ( x0 - delta[1].x, y0 - delta[1].y, z0 - delta[1].z );
00437     Dot3D fineBottomExcess   ( converter.fineX(x0) - delta[1].x,
00438                                converter.fineY(y0) - delta[1].y, 
00439                                converter.fineZ(z0) - delta[1].z );
00440     Dot3D coarseTopExcess( x1 + delta[1].x, y1 + delta[1].y, z1 + delta[1].z );
00441     Dot3D fineTopExcess  ( converter.fineX(x1) + delta[1].x,
00442                             converter.fineY(y1) + delta[1].y,
00443                             converter.fineZ(z1) + delta[1].z );
00444     
00445     // leftOutOfRange is true if interpolations are out-of-range on the left side of the domain.
00446     bool leftOutOfRange = ( !contained(coarseLeftExcess, coarseLattice.getBoundingBox()) ||
00447                             !contained(fineLeftExcess  , fineLattice.getBoundingBox()  ) );
00448     // rightOutOfRange is true if interpolations are out-of-range on the right side of the domain.
00449     bool rightOutOfRange = ( !contained(coarseRightExcess, coarseLattice.getBoundingBox()) ||
00450                              !contained(fineRightExcess  , fineLattice.getBoundingBox()  ) );
00451     // bottomOutOfRange is true if interpolations are out-of-range on the bottom of the domain.
00452     bool bottomOutOfRange = ( !contained(coarseBottomExcess, coarseLattice.getBoundingBox()) ||
00453                               !contained(fineBottomExcess  , fineLattice.getBoundingBox()) );
00454     // topOutOfRange is true if interpolations are out-of-range on the top of the domain.
00455     bool topOutOfRange = ( !contained(coarseTopExcess, coarseLattice.getBoundingBox()) ||
00456                            !contained(fineTopExcess  , fineLattice.getBoundingBox()  ) );
00457     
00458     // STEP 1: We take 4 sites of the coarse grid and we interpolate all the fine values inside
00459     for (plint iX=x0; iX<=x1-delta[2].x; ++iX) {
00460         for (plint iY=y0; iY<=y1-delta[2].y; ++iY){
00461             for (plint iZ=z0; iZ<=z1-delta[2].z; ++iZ){
00462                 // inserting the corresponding coarse values inside the 2D
00463                 // interpolation engine
00464                 interpolationEngine->pushToCouple (
00465                     Array<Cell<T,Descriptor1>,2>( coarseLattice.get(iX, iY, iZ),
00466                                                   coarseLattice.get(iX+delta[0].x,
00467                                                                iY+delta[0].y,
00468                                                                iZ+delta[0].z)),
00469                     *rescaleEngine );
00470                 interpolationEngine->pushToCouple (
00471                     Array<Cell<T,Descriptor1>,2>(coarseLattice.get( iX+delta[1].x,
00472                                                                     iY+delta[1].y,
00473                                                                     iZ+delta[1].z),
00474                                                      coarseLattice.get( iX+delta[2].x,
00475                                                                         iY+delta[2].y,
00476                                                                         iZ+delta[2].z)),
00477                     *rescaleEngine );
00478                 
00479                     
00480                 // copy of the values from the coarse to the fine
00481                 interpolationEngine->copyFrom (
00482                     converter.fineDynamics(iX,iY,iZ, 0,0,0).getDecomposedValues(whichTime), 0 );
00483                 interpolationEngine->copyFrom (
00484                     converter.fineDynamics(iX+delta[0].x,iY+delta[0].y,iZ+delta[0].z,
00485                                            0,0,0).getDecomposedValues(whichTime), 1 );
00486                 interpolationEngine->copyFrom (
00487                     converter.fineDynamics(iX+delta[1].x,iY+delta[1].y,iZ+delta[1].z,
00488                                            0,0,0).getDecomposedValues(whichTime), 2 );
00489                 interpolationEngine->copyFrom (
00490                     converter.fineDynamics(iX+delta[2].x,iY+delta[2].y,iZ+delta[2].z,
00491                                            0,0,0).getDecomposedValues(whichTime), 3 );
00492                 
00493                 // interpolate the 5 missing values
00494                 interpolationEngine->interpolateFromCouple (
00495                         converter.fineDynamics(iX,iY,iZ,
00496                                                delta[0].x, delta[0].y,delta[0].z).getDecomposedValues(whichTime), 0,1 );
00497                 interpolationEngine->interpolateFromCouple (
00498                         converter.fineDynamics(iX,iY,iZ,
00499                                                delta[1].x, delta[1].y,delta[1].z).getDecomposedValues(whichTime), 0,2 );
00500                 interpolationEngine->interpolateFromCouple (
00501                         converter.fineDynamics(iX+delta[0].x,iY+delta[0].y,iZ+delta[0].z,
00502                                                delta[1].x, delta[1].y,delta[1].z).getDecomposedValues(whichTime), 1,3 );
00503                 interpolationEngine->interpolateFromCouple (
00504                         converter.fineDynamics(iX+delta[1].x,iY+delta[1].y,iZ+delta[1].z,
00505                                                delta[0].x, delta[0].y,delta[0].z).getDecomposedValues(whichTime), 2,3 );
00506                 // this interpolation uses the four coarse values stored                              
00507                 interpolationEngine->interpolateFromAll(
00508                         converter.fineDynamics( iX,iY,iZ, 
00509                                                delta[2].x,delta[2].y,delta[2].z ).getDecomposedValues(whichTime) );     
00510                       
00511             }
00512         }
00513     }
00514     
00515     
00516     // STEP 2: We perform interpolations over the excedent regions of the grid if needed
00517     if (!leftOutOfRange){
00518         std::vector<Dot3D> deltas; 
00519         deltas.push_back(Dot3D(delta[1].x,delta[1].y,delta[1].z));
00520         deltas.push_back(Dot3D(-delta[0].x,-delta[0].y,-delta[0].z));
00521         InterpolateOverLineAndExcess<T,Descriptor1>( createLeftDomain(coarseDomain,direction), 
00522                                                      coarseLattice, fineLattice,
00523                                                      interpolationEngine->clone(), rescaleEngine->clone(),
00524                                                      deltas );
00525         
00526     }
00527     
00528     if (!bottomOutOfRange){
00529         std::vector<Dot3D> deltas; 
00530         deltas.push_back(Dot3D(delta[0].x,delta[0].y,delta[0].z));
00531         deltas.push_back(Dot3D(-delta[1].x,-delta[1].y,-delta[1].z));
00532         InterpolateOverLineAndExcess<T,Descriptor1>( createBottomDomain(coarseDomain,direction), 
00533                                                      coarseLattice, fineLattice,
00534                                                      interpolationEngine->clone(), rescaleEngine->clone(),
00535                                                      deltas );
00536     }
00537     
00538     if (!topOutOfRange){
00539         std::vector<Dot3D> deltas; 
00540         deltas.push_back(Dot3D(delta[0].x,delta[0].y,delta[0].z));
00541         deltas.push_back(Dot3D(delta[1].x,delta[1].y,delta[1].z));
00542         InterpolateOverLineAndExcess<T,Descriptor1>( createTopDomain(coarseDomain,direction), 
00543                                                      coarseLattice, fineLattice,
00544                                                      interpolationEngine->clone(), rescaleEngine->clone(),
00545                                                      deltas );
00546     }
00547     
00548     if (!rightOutOfRange){
00549         std::vector<Dot3D> deltas; 
00550         deltas.push_back(Dot3D(delta[1].x,delta[1].y,delta[1].z));
00551         deltas.push_back(Dot3D(delta[0].x,delta[0].y,delta[0].z));
00552         InterpolateOverLineAndExcess<T,Descriptor1>( createRightDomain(coarseDomain,direction), 
00553                                                      coarseLattice, fineLattice,
00554                                                      interpolationEngine->clone(), rescaleEngine->clone(),
00555                                                      deltas );
00556     }
00557     
00558     // STEP 3: We perform interpolations over the excedent corners if needed 
00559     std::vector<Box3D> corners = createCorners(coarseDomain,direction);
00560     
00561     if (!leftOutOfRange && !topOutOfRange){
00562         const Dot3D deltas[2] = {Dot3D(delta[1].x,delta[1].y,delta[1].z),Dot3D(-delta[0].x,-delta[0].y,-delta[0].z)};
00563         applyProcessingFunctional(
00564             new InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>(
00565                 rescaleEngine->clone(), interpolationEngine->clone(),
00566                 deltas
00567             ),
00568             corners[0],
00569             coarseLattice, fineLattice
00570         );
00571     }
00572     
00573     if (!leftOutOfRange && !bottomOutOfRange){
00574         const Dot3D deltas[2] = {Dot3D(-delta[1].x,-delta[1].y,-delta[1].z),Dot3D(-delta[0].x,-delta[0].y,-delta[0].z)};
00575         applyProcessingFunctional(
00576             new InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>(
00577                 rescaleEngine->clone(), interpolationEngine->clone(),
00578                 deltas
00579             ),
00580             corners[1],
00581             coarseLattice, fineLattice
00582         );
00583     }
00584     if (!rightOutOfRange && !bottomOutOfRange){
00585         const Dot3D deltas[2] = {Dot3D(-delta[1].x,-delta[1].y,-delta[1].z),Dot3D(delta[0].x,delta[0].y,delta[0].z)};
00586         applyProcessingFunctional(
00587             new InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>(
00588                 rescaleEngine->clone(), interpolationEngine->clone(),
00589                 deltas
00590             ),
00591             corners[2],
00592             coarseLattice, fineLattice
00593         );
00594     }    
00595     if (!rightOutOfRange && !topOutOfRange){
00596         const Dot3D deltas[2] = {Dot3D(delta[1].x,delta[1].y,delta[1].z),Dot3D(delta[0].x,delta[0].y,delta[0].z)};
00597         applyProcessingFunctional(
00598             new InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>(
00599                 rescaleEngine->clone(), interpolationEngine->clone(),
00600                 deltas
00601             ),
00602             corners[3],
00603             coarseLattice, fineLattice
00604         );
00605     }
00606 }
00607 
00608 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00609 InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>*
00610     InterpolateCoarseToFineDynamics3D<T,Descriptor1,Descriptor2>::clone() const
00611 {
00612     return new InterpolateCoarseToFineDynamics3D(*this);
00613 }
00614 
00615 
00616 
00617 /* *************** Class InterpolateCoarseToFineBoundaryDynamics3D ********** */
00618 
00619 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00620 InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>::InterpolateCoarseToFineBoundaryDynamics3D (
00621         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00622         InterpolationEngine2D<T,Descriptor1>* interpolationEngine_,
00623         const Dot3D delta_[2] )
00624     : rescaleEngine(rescaleEngine_),
00625       interpolationEngine(interpolationEngine_)
00626       
00627 { 
00628     delta.push_back(delta_[0]);
00629     delta.push_back(delta_[1]);
00630 }
00631 
00632 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00633 InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>::InterpolateCoarseToFineBoundaryDynamics3D (
00634         InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2> const& rhs )
00635     : rescaleEngine(rhs.rescaleEngine->clone()),
00636       interpolationEngine(rhs.interpolationEngine->clone()), delta(rhs.delta)
00637       
00638 { }
00639 
00640 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00641 InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>&
00642     InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>::operator= (
00643         InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2> const& rhs )
00644 {
00645     delete rescaleEngine;
00646     rescaleEngine = rhs.rescaleEngine->clone();
00647     delete interpolationEngine;
00648     interpolationEngine = rhs.interpolationEngine->clone();
00649     delta.resize(0);
00650     delta.push_back(rhs.delta[0]);
00651     delta.push_back(rhs.delta[1]);
00652     
00653 }
00654 
00655 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00656 InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>::~InterpolateCoarseToFineBoundaryDynamics3D()
00657 {
00658     delete rescaleEngine;
00659     delete interpolationEngine;
00660 }
00661 
00662 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00663 void InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>::process (
00664          Box3D domain,
00665          BlockLattice3D<T,Descriptor1>& coarseLattice,
00666          BlockLattice3D<T,Descriptor2>& fineLattice )
00667 {
00668     InterpolateOverLineAndExcess<T,Descriptor1>(domain, coarseLattice, fineLattice,
00669                                                 interpolationEngine->clone(), rescaleEngine->clone(),
00670                                                 delta);
00671     
00672 }
00673 
00674 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00675 InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>*
00676     InterpolateCoarseToFineBoundaryDynamics3D<T,Descriptor1,Descriptor2>::clone() const
00677 {
00678     return new InterpolateCoarseToFineBoundaryDynamics3D(*this);
00679 }
00680 
00681 /* *************** Class InterpolateCoarseToFineCornerDynamics3D ********** */
00682 
00683 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00684 InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>::InterpolateCoarseToFineCornerDynamics3D (
00685         RescaleEngine<T,Descriptor1>* rescaleEngine_,
00686         InterpolationEngine2D<T,Descriptor1>* interpolationEngine_,
00687         const Dot3D delta_[2])
00688     : rescaleEngine(rescaleEngine_),
00689       interpolationEngine(interpolationEngine_)     
00690 {
00691     delta.push_back(delta_[0]);
00692     delta.push_back(delta_[1]);
00693 }
00694 
00695 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00696 InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>::InterpolateCoarseToFineCornerDynamics3D (
00697         InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2> const& rhs )
00698     : rescaleEngine(rhs.rescaleEngine->clone()),
00699       interpolationEngine(rhs.interpolationEngine->clone()), delta(rhs.delta)
00700 {}
00701 
00702 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00703 InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>&
00704     InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>::operator= (
00705         InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2> const& rhs )
00706 {
00707     delete rescaleEngine;
00708     rescaleEngine = rhs.rescaleEngine->clone();
00709     delete interpolationEngine;
00710     interpolationEngine = rhs.interpolationEngine->clone();
00711     delta.resize(0);
00712     delta.push_back(rhs.delta[0]);
00713     delta.push_back(rhs.delta[1]);
00714 }
00715 
00716 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00717 InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>::~InterpolateCoarseToFineCornerDynamics3D()
00718 {
00719     delete rescaleEngine;
00720     delete interpolationEngine;
00721 }
00722 
00723 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00724 void InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>::process (
00725          Box3D domain,
00726          BlockLattice3D<T,Descriptor1>& coarseLattice,
00727          BlockLattice3D<T,Descriptor2>& fineLattice )
00728 {
00729     PLB_PRECONDITION( domain.x0 == domain.x1 );
00730     PLB_PRECONDITION( domain.y0 == domain.y1 );
00731     PLB_PRECONDITION( domain.z0 == domain.z1 );
00732 
00733     plint x0 = domain.x0;
00734     plint y0 = domain.y0;
00735     plint z0 = domain.z0;
00736 
00737     plint whichTime = 1;
00738     CoarseToFineConverter3D<T,Descriptor1> converter(coarseLattice, fineLattice);
00739 
00740     // Check if the extended domain (over which the interpolation is executed) exceeds either
00741     //   the coarse or the fine lattice, in which case interpolation is not executed.
00742     Dot3D coarseExcess1 ( x0 + delta[0].x, y0 + delta[0].y, z0 + delta[0].z );
00743     Dot3D fineExcess1   ( converter.fineX(x0) + delta[0].x,
00744                          converter.fineY(y0) + delta[0].y, 
00745                          converter.fineZ(z0) + delta[0].z );
00746     Dot3D coarseExcess2 ( x0 + delta[1].x, y0 + delta[1].y, z0 + delta[1].z );
00747     Dot3D fineExcess2   ( converter.fineX(x0) + delta[1].x,
00748                          converter.fineY(y0) + delta[1].y, 
00749                          converter.fineZ(z0) + delta[1].z );                     
00750     
00751     bool outOfRange1 = ( !contained( coarseExcess1, coarseLattice.getBoundingBox()) ||
00752                          !contained( fineExcess1  , fineLattice.getBoundingBox()) );
00753     bool outOfRange2 = ( !contained( coarseExcess2, coarseLattice.getBoundingBox()) ||
00754                          !contained( fineExcess2  , fineLattice.getBoundingBox()) );
00755 
00756     // Copy coarse->left on the chosen cell, and execute interpolation, unless the
00757     //   interpolation is out-of-range.
00758     if (!outOfRange1){
00759         interpolationEngine->pushToCouple (
00760                 Array<Cell<T,Descriptor1>,2>(coarseLattice.get(x0, y0, z0),
00761                                              coarseLattice.get(x0+delta[0].x,
00762                                                                y0+delta[0].y,
00763                                                                z0+delta[0].z)),
00764                 *rescaleEngine );
00765     }
00766     
00767     if (outOfRange2){
00768         interpolationEngine->pushToCouple();
00769     }
00770     else {
00771         interpolationEngine->pushToCouple (
00772                 Array<Cell<T,Descriptor1>,2>(coarseLattice.get(x0+delta[1].x, y0+delta[1].y, z0+delta[1].z),
00773                                              coarseLattice.get(x0+delta[0].x+delta[1].x,
00774                                                                y0+delta[0].y+delta[1].y,
00775                                                                z0+delta[0].z+delta[1].z)),
00776                 *rescaleEngine );
00777     }
00778 
00779     
00780     interpolationEngine->copyFrom (
00781             converter.fineDynamics(x0,y0,z0, 0,0,0).getDecomposedValues(whichTime), 0 );
00782 
00783     if (!outOfRange1) {
00784         interpolationEngine->interpolateFromCouple (
00785             converter.fineDynamics(x0,y0,z0, delta[0].x, delta[0].y, delta[0].z).getDecomposedValues(whichTime), 0,1 );
00786     }
00787     
00788     if (!outOfRange2) {
00789         interpolationEngine->interpolateFromCouple (
00790             converter.fineDynamics(x0,y0,z0, delta[1].x, delta[1].y, delta[1].z).getDecomposedValues(whichTime), 0,2 );
00791     }
00792     
00793     if (!outOfRange1 && !outOfRange2){
00794         interpolationEngine->interpolateFromAll(
00795             converter.fineDynamics(x0,y0,z0, 
00796                                    delta[1].x+delta[0].x,
00797                                    delta[1].y+delta[0].y,
00798                                    delta[1].z+delta[0].z).getDecomposedValues(whichTime) );
00799     }
00800     
00801 }
00802 
00803 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00804 InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>*
00805     InterpolateCoarseToFineCornerDynamics3D<T,Descriptor1,Descriptor2>::clone() const
00806 {
00807     return new InterpolateCoarseToFineCornerDynamics3D(*this);
00808 }
00809 
00810 
00811 
00812 
00813 /* *************** Class Copy_t1_to_t0_3D *********************************** */
00814 
00815 template<typename T, template<typename U> class Descriptor>
00816 Copy_t1_to_t0_3D<T,Descriptor>::Copy_t1_to_t0_3D(plint numTimeSteps_, plint executionTime_)
00817     : numTimeSteps(numTimeSteps_),
00818       executionTime(executionTime_)
00819 { }
00820 
00821 template<typename T, template<typename U> class Descriptor>
00822 void Copy_t1_to_t0_3D<T,Descriptor>::process(Box3D domain, BlockLattice3D<T,Descriptor>& fineLattice)
00823 {
00824     // Determine current relative value of time steps.
00825     size_t relativeTime = fineLattice.getTimeCounter().getTime()%numTimeSteps;
00826     // Execute data processor only if one is at the end of a cycle.
00827     if ((plint)relativeTime==executionTime) {
00828         for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00829             for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00830                 for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00831                     FineGridBoundaryDynamics<T,Descriptor>& fineDynamics =
00832                         dynamic_cast<FineGridBoundaryDynamics<T,Descriptor>&>
00833                             ( fineLattice.get(iX,iY,iZ).getDynamics() );
00834                     std::vector<T>& t0 = fineDynamics.getDecomposedValues(0);
00835                     std::vector<T>& t1 = fineDynamics.getDecomposedValues(1);
00836                     t0.assign(t1.begin(), t1.end());
00837                 }
00838             }
00839         }
00840     }
00841 }
00842 
00843 template<typename T, template<typename U> class Descriptor>
00844 Copy_t1_to_t0_3D<T,Descriptor>* Copy_t1_to_t0_3D<T,Descriptor>::clone() const {
00845     return new Copy_t1_to_t0_3D(*this);
00846 }
00847 
00848 
00849 /* *************** Class CopyFineToCoarse3D ********************************* */
00850 
00851 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00852 CopyFineToCoarse3D<T,Descriptor1,Descriptor2>::CopyFineToCoarse3D (
00853         RescaleEngine<T,Descriptor1>* rescaleEngine_, plint numTimeSteps_, plint executionTime_ )
00854     : rescaleEngine(rescaleEngine_),
00855       numTimeSteps(numTimeSteps_),
00856       executionTime(executionTime_)
00857 { }
00858 
00859 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00860 CopyFineToCoarse3D<T,Descriptor1,Descriptor2>::~CopyFineToCoarse3D() {
00861     delete rescaleEngine;
00862 }
00863 
00864 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00865 CopyFineToCoarse3D<T,Descriptor1,Descriptor2>::CopyFineToCoarse3D(CopyFineToCoarse3D<T,Descriptor1,Descriptor2> const&
00866 rhs)
00867     : rescaleEngine(rhs.rescaleEngine->clone()),
00868       numTimeSteps(rhs.numTimeSteps),
00869       executionTime(rhs.executionTime)
00870 { }
00871 
00872 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00873 CopyFineToCoarse3D<T,Descriptor1,Descriptor2>& CopyFineToCoarse3D<T,Descriptor1,Descriptor2>::operator= (
00874         CopyFineToCoarse3D<T,Descriptor1,Descriptor2> const& rhs )
00875 {
00876     delete rescaleEngine;
00877     rescaleEngine = rhs.rescaleEngine->clone();
00878     numTimeSteps = rhs.numTimeSteps;
00879     executionTime = rhs.executionTime;
00880 }
00881 
00882 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00883 void CopyFineToCoarse3D<T,Descriptor1,Descriptor2>::process (
00884          Box3D fineDomain,
00885          BlockLattice3D<T,Descriptor1>& fineLattice,
00886          BlockLattice3D<T,Descriptor2>& coarseLattice )
00887 {
00888     PLB_PRECONDITION( fineDomain.x0==fineDomain.x1 ||
00889                       fineDomain.y0==fineDomain.y1 ||
00890                       fineDomain.z0==fineDomain.z1);
00891 
00892     // Determine current relative value of time steps
00893     size_t relativeTime = fineLattice.getTimeCounter().getTime()%numTimeSteps;
00894     // Execute data processor only if one is at the end of a cycle (iT=1)
00895     if ((plint)relativeTime==executionTime) {
00896         Dot3D posFine = fineLattice.getLocation();      // Position of fine grid in multi block.
00897         Dot3D posCoarse = coarseLattice.getLocation();  // Position of coarse grid in multi block.
00898         Box3D coarseDomain (
00899                 fineDomain.shift(posFine.x,posFine.y,posFine.z).        // Convert to absolute fine coordinates.
00900                     divideAndFitSmaller(2).                             // Rescale, but don't exceed original domain.
00901                         shift(-posCoarse.x,-posCoarse.y,-posCoarse.z) ); // Convert to relative coarse coordinates.
00902         std::vector<T> decomposedCoarseValues;
00903         // Loop over coarse lattice
00904         for (plint iX=coarseDomain.x0; iX<=coarseDomain.x1; ++iX) {
00905             for (plint iY=coarseDomain.y0; iY<=coarseDomain.y1; ++iY) {
00906                 for (plint iZ=coarseDomain.z0; iZ<=coarseDomain.z1; ++iZ) {
00907                     // Determine corresonding coordinates on fine lattice
00908                     plint fineX = (iX+posCoarse.x)*2 - posFine.x;
00909                     plint fineY = (iY+posCoarse.y)*2 - posFine.y;
00910                     plint fineZ = (iZ+posCoarse.z)*2 - posFine.z;
00911 
00912                     Cell<T,Descriptor1>& coarseCell = coarseLattice.get(iX,iY,iZ);
00913                     Cell<T,Descriptor2> const& fineCell = fineLattice.get(fineX,fineY,fineZ);
00914 
00915                     rescaleEngine->scaleFineCoarse(fineCell, decomposedCoarseValues);
00916                     rescaleEngine->recompose(coarseCell, decomposedCoarseValues);
00917                 }
00918             }
00919         }
00920     }
00921 }
00922 
00923 template<typename T, template<typename U> class Descriptor1, template<typename U> class Descriptor2>
00924 CopyFineToCoarse3D<T,Descriptor1,Descriptor2>*
00925     CopyFineToCoarse3D<T,Descriptor1,Descriptor2>::clone() const
00926 {
00927     return new CopyFineToCoarse3D(*this);
00928 }
00929 
00930 }  // namespace plb
00931 
00932 #endif  // GRID_REFINEMENT_PROCESSORS_3D_HH