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

multiGridLattice2D.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 
00028 #ifndef MULTI_GRID_LATTICE_2D_HH
00029 #define MULTI_GRID_LATTICE_2D_HH
00030 
00031 #include "multiGrid/multiGridLattice2D.h"
00032 #include "multiGrid/multiGridParameterManager.h"
00033 
00034 #include "io/parallelIO.h"
00035 #include "core/util.h"
00036 
00037 namespace plb {
00038 
00039 /* ****** MultiGridLattice2D ****** */
00040 
00041 template <typename T, template <typename U> class Descriptor>
00042 MultiGridLattice2D<T,Descriptor>::MultiGridLattice2D( MultiGridManagement2D management,
00043                         Dynamics<T,Descriptor>* backgroundDynamics,
00044                         plint behaviorLevel,
00045                         FineGridInterfaceInstantiator<T,Descriptor> *fineGridInstantiator_,
00046                         CoarseGridInterfaceInstantiator<T,Descriptor> *coarseGridInstantiator_  )
00047        : MultiGrid2D (
00048              management,
00049              behaviorLevel ), fineGridInstantiator(fineGridInstantiator_),
00050              coarseGridInstantiator(coarseGridInstantiator_)
00051 {
00052     std::vector<Dynamics<T,Descriptor>*> dynamicsVector(this->getNumLevels());
00053     for (plint iLevel=0; iLevel<this->getNumLevels(); ++iLevel){
00054         Dynamics<T,Descriptor>* cloned = backgroundDynamics->clone();
00055         cloned->rescale(behaviorLevel-iLevel,behaviorLevel-iLevel);
00056         dynamicsVector[iLevel] = cloned;
00057     }
00058     delete backgroundDynamics;
00059     // generate the lattices that correspond to the blocks contained inside the management object
00060     lattices = generateLattices( this->getMultiGridManagement(), dynamicsVector,
00061                                  defaultMultiGridPolicy2D().getBlockCommunicator<T>(management.getNumLevels()),
00062                                  defaultMultiGridPolicy2D().getCombinedStatistics(management.getNumLevels()),
00063                                  fineGridInstantiator->getEnvelopeWidth());
00064                                  
00065     // initialize the internalStatSubscription (multiGrid) once all the lattices have been created
00066     this->internalStatSubscription().initialize();
00067 }
00068 
00069 template <typename T, template <typename U> class Descriptor>
00070 MultiGridLattice2D<T,Descriptor>::MultiGridLattice2D (
00071         MultiGridManagement2D management,
00072         std::vector<BlockCommunicator2D*> communicators_,
00073         std::vector<CombinedStatistics*> combinedStatistics_, 
00074         Dynamics<T,Descriptor>* backgroundDynamics,
00075         plint behaviorLevel,
00076         FineGridInterfaceInstantiator<T,Descriptor> *fineGridInstantiator_,
00077         CoarseGridInterfaceInstantiator<T,Descriptor> *coarseGridInstantiator_ )
00078     : MultiGrid2D( management,
00079                    behaviorLevel ), fineGridInstantiator(fineGridInstantiator_),
00080       coarseGridInstantiator(coarseGridInstantiator_)
00081 {
00082     std::vector<Dynamics<T,Descriptor>*> dynamicsVector(this->getNumLevels());
00083     for (plint iLevel=0; iLevel<this->getNumLevels(); ++iLevel){
00084         Dynamics<T,Descriptor>* cloned = backgroundDynamics->clone();
00085         cloned->rescale(behaviorLevel-iLevel,behaviorLevel-iLevel);
00086         dynamicsVector[iLevel] = cloned;
00087     }
00088     delete backgroundDynamics;
00089     // generate the lattices that correspond to the blocks contained inside the management object
00090     lattices = generateLattices( this->getMultiGridManagement(), dynamicsVector,
00091                                  communicators_, combinedStatistics_,
00092                                  fineGridInstantiator->getEnvelopeWidth() );
00093     // initialize the internalStatSubscription (multiGrid) once all the lattices have been created
00094     this->internalStatSubscription().initialize();
00095 }
00096 
00097 
00099 template <typename T, template <typename U> class Descriptor>
00100 MultiGridLattice2D<T,Descriptor>::~MultiGridLattice2D(){
00101     for (plint i = 0; i < this->getNumLevels(); ++i){
00102         delete lattices[i];
00103         // the dynamics are taken care by each lattice
00104     }
00105     
00106     delete fineGridInstantiator;
00107     delete coarseGridInstantiator;
00108 }
00109 
00110 //BUG: there is a problem with the copy constructor
00111 template <typename T, template <typename U> class Descriptor>
00112 MultiGridLattice2D<T,Descriptor>::MultiGridLattice2D(MultiGridLattice2D<T,Descriptor> const& rhs)
00113   : MultiGrid2D(rhs), fineGridInstantiator(rhs.fineGridInstantiator->clone()),
00114     coarseGridInstantiator(rhs.coarseGridInstantiator->clone())
00115 {
00116     std::vector<Dynamics<T,Descriptor>*> dynamicsVector(this->getNumLevels());
00117     
00118     for (plint iLevel=0; iLevel<this->getNumLevels(); ++iLevel){
00119         Dynamics<T,Descriptor>* cloned = rhs.lattices[iLevel]->getBackgroundDynamics().clone();
00120         dynamicsVector[iLevel] = cloned;
00121     }
00122     MultiGridManagement2D const& management = this->getMultiGridManagement();
00123     // generate the lattices that correspond to the blocks contained inside the management object
00124     lattices = generateLattices( management, dynamicsVector,
00125                                  defaultMultiGridPolicy2D().getBlockCommunicator<T>(management.getNumLevels()),
00126                                  defaultMultiGridPolicy2D().getCombinedStatistics(management.getNumLevels()),
00127                                  fineGridInstantiator->getEnvelopeWidth() );
00128                                  
00129     // initialize the internalStatSubscription (multiGrid) once all the lattices have been created
00130     this->internalStatSubscription().initialize();
00131 }
00132 
00133 
00134 template <typename T, template <typename U> class Descriptor>
00135 MultiGridLattice2D<T,Descriptor>::MultiGridLattice2D( MultiGridLattice2D<T,Descriptor> const& rhs, 
00136                                                       Box2D subDomain, bool crop )
00137   : MultiGrid2D(rhs, subDomain, crop), fineGridInstantiator(rhs.fineGridInstantiator),
00138     coarseGridInstantiator(rhs.coarseGridInstantiator)
00139 {
00140     std::vector<Dynamics<T,Descriptor>*> backgroundDynamics;
00141     for (plint iDyn=0; iDyn<this->getNumLevels(); ++iDyn) {
00142       backgroundDynamics[iDyn] = new NoDynamics<T,Descriptor>();
00143     }
00144     // generate the lattices that correspond to the blocks contained inside the management object
00145     lattices = generateLattices( this->getMultiGridManagement(), backgroundDynamics,
00146                                  this->getCommunicators(), this->getCombinedStatistics(),
00147                                  fineGridInstantiator->getEnvelopeWidth() );
00148                                  
00149     // initialize the internalStatSubscription (multiGrid) once all the lattices have been created
00150     this->internalStatSubscription().initialize();
00151 }
00152 
00153 
00154 template <typename T, template <typename U> class Descriptor>
00155 MultiGridLattice2D<T,Descriptor>::MultiGridLattice2D(MultiGrid2D const& rhs)
00156   : MultiGrid2D(rhs)
00157 {
00158     std::vector<Dynamics<T,Descriptor>*> backgroundDynamics;
00159     for (plint iDyn=0; iDyn<this->getNumLevels(); ++iDyn) {
00160       backgroundDynamics[iDyn] = new NoDynamics<T,Descriptor>();
00161     }
00162     // generate the lattices that correspond to the blocks contained inside the management object
00163     lattices = generateLattices( this->getMultiGridManagement(), backgroundDynamics,
00164                                  this->getCommunicators(), this->getCombinedStatistics() );
00165                                  
00166     // initialize the internalStatSubscription (multiGrid) once all the lattices have been created
00167     this->internalStatSubscription().initialize();
00168 
00169 }
00170 
00171 template <typename T, template <typename U> class Descriptor>
00172 MultiGridLattice2D<T,Descriptor>::MultiGridLattice2D( MultiGrid2D const& rhs, 
00173                                                       Box2D subDomain, bool crop )
00174   : MultiGrid2D(rhs, subDomain, crop)
00175 {
00176     std::vector<Dynamics<T,Descriptor>*> backgroundDynamics;
00177     for (plint iDyn=0; iDyn<this->getNumLevels(); ++iDyn) {
00178       backgroundDynamics[iDyn] = new NoDynamics<T,Descriptor>();
00179     }
00180     // generate the lattices that correspond to the blocks contained inside the management object
00181     lattices = generateLattices( this->getMultiGridManagement(), backgroundDynamics,
00182                                  this->getCommunicators(), this->getCombinedStatistics() );
00183                                  
00184     // initialize the internalStatSubscription (multiGrid) once all the lattices have been created
00185     this->internalStatSubscription().initialize();
00186 
00187 }
00188 
00189 template<typename T, template<typename U> class Descriptor>
00190 MultiGridLattice2D<T,Descriptor>& MultiGridLattice2D<T,Descriptor>::operator= (
00191         MultiGridLattice2D<T,Descriptor> const& rhs )
00192 {
00193     MultiGridLattice2D<T,Descriptor> tmp(rhs);
00194     swap(tmp);
00195     return *this;
00196 }
00197 
00198 
00202 template <typename T, template <typename U> class Descriptor>
00203 void MultiGridLattice2D<T,Descriptor>::initialize()
00204 {
00205     this->createInterfaces();
00206     
00207     // eliminate the statistics in the refinement overlap
00208     this->eliminateStatisticsInOverlap();
00209     
00210     // Execute this data processor once, because this allocates memory on the fine grid dynamcis
00211     //   for time t0 (after we have values for t1)
00212     lattices[0]->initialize();
00213     std::vector<std::vector<Box2D> > fineGridInterfaces = this->getMultiGridManagement().getFineInterface();
00214     plint timeForImmediateExecution = 0;
00215     plint numTimeSteps=2;
00216     // fineGrid interfaces start at level 1
00217     for (pluint iLevel=1; iLevel<fineGridInterfaces.size(); ++iLevel){
00218         std::vector<Box2D> levelInterfaces=fineGridInterfaces[iLevel];
00219         for (pluint iInterf=0; iInterf<levelInterfaces.size(); ++iInterf){
00220             applyProcessingFunctional (
00221                 new Copy_t1_to_t0_2D<T, Descriptor>(numTimeSteps, timeForImmediateExecution),
00222                 levelInterfaces[iInterf].multiply(2),
00223                 *lattices[iLevel] );
00224         }
00225         lattices[iLevel]->initialize();
00226     }
00227     
00228     // toggle all stats on
00229     for (int iLevel = 0; iLevel < (plint)lattices.size(); ++iLevel){
00230         lattices[iLevel]->toggleInternalStatistics(true);
00231     }
00232     
00233 }
00234 
00235 template <typename T, template <typename U> class Descriptor>
00236 void MultiGridLattice2D<T,Descriptor>::createInterfaces(){
00237     MultiGridManagement2D management = this->getMultiGridManagement();
00238     
00239     std::vector<std::vector<Box2D> > fineGridInterfaces   = management.getFineInterface();
00240     std::vector<std::vector<Box2D> > coarseGridInterfaces = management.getCoarseInterface();
00241     std::vector<std::vector<Array<plint,2> > > coarseOrientations = management.getCoarseOrientation();
00242     std::vector<std::vector<Array<plint,2> > > fineOrientations   = management.getFineOrientation();
00243 
00244     // Create the part of the coupling in which a lattice acts as a coarse lattice.
00245     for (pluint iCoarse=0; iCoarse<lattices.size()-1; ++iCoarse) {
00246         for (pluint iInterface=0; iInterface<coarseGridInterfaces[iCoarse].size(); ++iInterface) {
00247             plint direction = (coarseOrientations[iCoarse][iInterface])[0]; // w.r.t. the coarse grid
00248             plint orientation = (coarseOrientations[iCoarse][iInterface])[1]; // w.r.t. the coarse grid
00249             coarseGridInstantiator->instantiateDataProcessors(coarseGridInterfaces[iCoarse][iInterface],
00250                                                             *lattices[iCoarse],*lattices[iCoarse+1],
00251                                                             direction, orientation);
00252         }
00253     }
00254     // Create the part of the coupling in which a lattice acts as a fine lattice.
00255     for (pluint iFine=1; iFine<lattices.size(); ++iFine) {
00256         for (pluint iInterface=0; iInterface<fineGridInterfaces[iFine].size(); ++iInterface) {
00257             plint direction = (fineOrientations[iFine][iInterface])[0]; // w.r.t. the fine grid
00258             plint orientation = (fineOrientations[iFine][iInterface])[1]; // w.r.t. the fine grid
00259             fineGridInstantiator->instantiateDataProcessors(fineGridInterfaces[iFine][iInterface],
00260                                                             *lattices[iFine-1],*lattices[iFine],
00261                                                             direction, orientation);
00262         }
00263     }
00264 }
00265 
00266 /* *** MultiGrid2D methods *** */
00268 template <typename T, template <typename U> class Descriptor>
00269 MultiBlockLattice2D<T,Descriptor>& MultiGridLattice2D<T,Descriptor>::getComponent(plint iBlock)
00270 {
00271     PLB_PRECONDITION( iBlock >= 0 && iBlock < (plint) lattices.size() );
00272     return *lattices[iBlock];
00273 }
00274 
00275 template <typename T, template <typename U> class Descriptor>
00276 const MultiBlockLattice2D<T,Descriptor>& MultiGridLattice2D<T,Descriptor>::getComponent(plint iBlock) const
00277 {
00278     PLB_PRECONDITION( iBlock >= 0 && iBlock < (plint) lattices.size() );
00279     return *lattices[iBlock];
00280 }
00281 
00282 /* **** BlockLatticeBase2D methods **** */
00283 
00284 template <typename T, template <typename U> class Descriptor>
00285 Cell<T,Descriptor>& MultiGridLattice2D<T,Descriptor>::get(plint iX, plint iY){
00286     return lattices[this->getBehaviorLevel()]->get(iX,iY);
00287 }
00288 
00289 template <typename T, template <typename U> class Descriptor>
00290 Cell<T,Descriptor> const& MultiGridLattice2D<T,Descriptor>::get(plint iX, plint iY) const{
00291     return lattices[this->getBehaviorLevel()]->get(iX,iY);
00292 }
00293 
00294 template <typename T, template <typename U> class Descriptor>
00295 void MultiGridLattice2D<T,Descriptor>::specifyStatisticsStatus(Box2D domain, bool status){
00296     for (plint iLevel = 0; iLevel < (plint)lattices.size(); ++iLevel){
00297         Box2D rescaledDomain = this->getScaleManager().scaleBox(domain,iLevel);
00298         lattices[iLevel]->specifyStatisticsStatus(rescaledDomain,status);
00299     }
00300 }
00301 
00302 
00303 template <typename T, template <typename U> class Descriptor>
00304 void MultiGridLattice2D<T,Descriptor>::collide(Box2D domain){
00305     plint levelNumber = (plint)lattices.size();
00306     PLB_PRECONDITION( levelNumber >= 0 && levelNumber <= (plint)lattices.size() );
00307     for (plint iLevel = 0; iLevel < levelNumber; ++iLevel){
00308         // each level will iterate 2 times the iterations of level - 1
00309         plint fineGridIt = util::roundToInt(util::twoToThePower(iLevel));
00310         for (plint iterations = 0; iterations < fineGridIt; ++iterations){
00311             lattices[iLevel]->collide(domain);
00312         }
00313     }
00314 }
00315 
00316 template <typename T, template <typename U> class Descriptor>
00317 void MultiGridLattice2D<T,Descriptor>::collide() {
00318     plint levelNumber = (plint)lattices.size();
00319     PLB_PRECONDITION( levelNumber >= 0 && levelNumber <= (plint)lattices.size() );
00320     for (plint iLevel = 0; iLevel < levelNumber; ++iLevel){
00321         // each level will iterate 2 times the iterations of level - 1
00322         plint fineGridIt = util::roundToInt(util::twoToThePower(iLevel));
00323         for (plint iterations = 0; iterations < fineGridIt; ++iterations){
00324             lattices[iLevel]->collide();
00325         }
00326     }
00327 }
00328 
00329 template <typename T, template <typename U> class Descriptor>
00330 void MultiGridLattice2D<T,Descriptor>::stream(Box2D domain) {
00331     plint levelNumber = (plint)lattices.size();
00332     PLB_PRECONDITION( levelNumber >= 0 && levelNumber <= (plint)lattices.size() );
00333     for (plint iLevel = 0; iLevel < levelNumber; ++iLevel){
00334         // each level will iterate 2 times the iterations of level - 1
00335         plint fineGridIt = util::roundToInt(util::twoToThePower(iLevel));
00336         for (plint iterations = 0; iterations < fineGridIt; ++iterations){
00337             lattices[iLevel]->stream(domain);
00338         }
00339     }
00340 }
00341 
00342 template <typename T, template <typename U> class Descriptor>
00343 void MultiGridLattice2D<T,Descriptor>::stream() {
00344     plint levelNumber = (plint)lattices.size();
00345     PLB_PRECONDITION( levelNumber >= 0 && levelNumber <= (plint)lattices.size() );
00346     for (plint iLevel = 0; iLevel < levelNumber; ++iLevel){
00347         // each level will iterate 2 times the iterations of level - 1
00348         plint fineGridIt = util::roundToInt(util::twoToThePower(iLevel));
00349         for (plint iterations = 0; iterations < fineGridIt; ++iterations){
00350                 lattices[iLevel]->stream();
00351         }
00352         // update the values for parallelism
00353         lattices[iLevel]->getBlockCommunicator().duplicateOverlaps(*lattices[iLevel], modif::staticVariables);
00354     }
00355     
00356     this->evaluateStatistics();
00357 }
00358 
00360 template <typename T, template <typename U> class Descriptor>
00361 void MultiGridLattice2D<T,Descriptor>::collideAndStream(Box2D domain){
00362     plint levelNumber = (plint)lattices.size();
00363     PLB_PRECONDITION( levelNumber >= 0 && levelNumber <= (plint)lattices.size() );
00364     for (plint iLevel = 0; iLevel < levelNumber; ++iLevel){
00365         // each level will iterate 2 times the iterations of level - 1
00366         plint fineGridIt = util::roundToInt(util::twoToThePower(iLevel));
00367         for (plint iterations = 0; iterations < fineGridIt; ++iterations){
00368             lattices[iLevel]->collideAndStream(domain);
00369         }
00370     }
00371 }
00372 
00373 
00374 template <typename T, template <typename U> class Descriptor>
00375 void MultiGridLattice2D<T,Descriptor>::iterateMultiGrid(plint level){
00376     PLB_PRECONDITION( level>=0 && level<(plint)lattices.size() );
00377     lattices[level]->collideAndStream();
00378     if ((pluint)level<lattices.size()-1) {
00379         iterateMultiGrid(level+1);
00380         iterateMultiGrid(level+1);
00381         // Overlaps must be duplicated on the coarse lattice, because the
00382         //   fine->coarse copy acts on bulk nodes only.
00383         lattices[level]->getBlockCommunicator().duplicateOverlaps(*lattices[level], modif::staticVariables);
00384     }
00385 }
00386 
00388 template <typename T, template <typename U> class Descriptor>
00389 void MultiGridLattice2D<T,Descriptor>::collideAndStream(){
00390     iterateMultiGrid(0);
00391     this->evaluateStatistics();
00392 }
00393 
00397 template <typename T, template <typename U> class Descriptor>
00398 void MultiGridLattice2D<T,Descriptor>::incrementTime()
00399 {}
00400 
00401 template <typename T, template <typename U> class Descriptor>
00402 TimeCounter& MultiGridLattice2D<T,Descriptor>::getTimeCounter(){
00403     return lattices[this->getBehaviorLevel()]->getTimeCounter();
00404 }
00405 
00406 template <typename T, template <typename U> class Descriptor>
00407 TimeCounter const& MultiGridLattice2D<T,Descriptor>::getTimeCounter() const{
00408     return lattices[this->getBehaviorLevel()]->getTimeCounter();
00409 }
00410 
00411 template <typename T, template <typename U> class Descriptor>
00412 int  MultiGridLattice2D<T,Descriptor>::getBlockId () const{
00413     return lattices[this->getReferenceLevel()]->getStaticId();
00414 }
00415 
00420 template <typename T, template <typename U> class Descriptor>
00421 void MultiGridLattice2D<T,Descriptor>::eliminateStatisticsInOverlap(){
00422     // the fine interface is the region inside the fine grid that overlaps with the coarse
00423     //   grid. It is therefore there that we need to turn off the statistics in the 
00424     //   coarse grid.
00425     std::vector<std::vector<Box2D> > fineOverlaps = this->getMultiGridManagement().getFineInterface();
00426     for (plint iLevel = 0; iLevel < (plint)lattices.size()-1; ++iLevel){
00427         for (plint iOv = 0; iOv < (plint)fineOverlaps[iLevel].size(); ++iOv){
00428             Box2D currentOverlap = (fineOverlaps[iLevel])[iOv];
00429             lattices[iLevel]->specifyStatisticsStatus(currentOverlap, false);
00430         }
00431     }
00432     // it is also necessary to avoid computation in the coarse interface, as the refinement 
00433     //   overlap is two coarse sites
00434     std::vector<std::vector<Box2D> > coarseOverlaps = this->getMultiGridManagement().getCoarseInterface();
00435     for (plint iLevel = 0; iLevel < (plint)lattices.size()-1; ++iLevel){
00436         for (plint iOv = 0; iOv < (plint)coarseOverlaps[iLevel].size(); ++iOv){
00437             Box2D currentOverlap = (coarseOverlaps[iLevel])[iOv];
00438             lattices[iLevel]->specifyStatisticsStatus(currentOverlap, false);
00439         }
00440     }
00441     
00442 }
00443 
00444 
00449 template <typename T, template <typename U> class Descriptor>
00450 std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > MultiGridLattice2D<T,Descriptor>::convertToLevel(plint level) const
00451 {
00452     // create the resulting multiBlock
00453     std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > result = 
00454         generateMultiBlockLattice<T,Descriptor>(
00455                                 lattices[level]->getBoundingBox(),
00456                                 lattices[level]->getBackgroundDynamics().clone(),
00457                                 lattices[level]->getMultiBlockManagement().getEnvelopeWidth() );
00458                                 
00459     // create the first lattice to start looping
00460     std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > refined = 
00461         generateMultiBlockLattice<T,Descriptor>(
00462                                 lattices[0]->getBoundingBox(),
00463                                 lattices[0]->getBackgroundDynamics().clone(),
00464                                 lattices[0]->getMultiBlockManagement().getEnvelopeWidth() );
00465 
00466     copyNonLocal<T,Descriptor>(*lattices[0],*refined, 
00467                                refined->getBoundingBox(), modif::staticVariables);
00468     
00469     // loop to interpolate the blocks until level-1
00470     for (plint iLevel=0; iLevel<(plint)level; ++iLevel){
00471         plint envelopeWidth = lattices[iLevel+1]->getMultiBlockManagement().getEnvelopeWidth();
00472         // interpolate lattice at iLevel
00473         std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > tmp = 
00474             refine(*refined,-1,-1,refined->getBackgroundDynamics().clone());
00475         
00476         refined = generateMultiBlockLattice<T,Descriptor>(lattices[iLevel+1]->getBoundingBox(),
00477                                                     lattices[iLevel+1]->getBackgroundDynamics().clone(),
00478                                                     envelopeWidth );
00479 
00480         // copy from reshaped iLevel to result
00481         copyNonLocal<T,Descriptor>(*tmp, *refined, refined->getBoundingBox(),modif::staticVariables);
00482         // copy from iLevel+1 to result
00483         copyNonLocal<T,Descriptor>(*lattices[iLevel+1], *refined, refined->getBoundingBox(),modif::staticVariables);
00484     }
00485     
00486     // create the last lattice to start looping in the other orientation
00487     plint lastLevel = getNumLevels()-1;
00488     std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > coarsened = 
00489         std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > ( 
00490                     new MultiBlockLattice2D<T,Descriptor>(*lattices[lastLevel]));
00491                     
00492     defineDynamics<T,Descriptor>( *coarsened, coarsened->getBoundingBox(),
00493                                   lattices[lastLevel]->getBackgroundDynamics().clone() );
00494                                 
00495     copyNonLocal<T,Descriptor>(*lattices[lastLevel],*coarsened,
00496                                coarsened->getBoundingBox(),  modif::staticVariables);
00497     
00498     // loop to decimate the blocks until level+1
00499     for (plint iLevel=getNumLevels()-1; iLevel>=(plint)level+1; --iLevel){
00500         // interpolate lattice at iLevel
00501         std::auto_ptr<MultiBlockLattice2D<T,Descriptor> > tmp = 
00502             coarsen(*coarsened,1,1, lattices[iLevel]->getBackgroundDynamics().clone() );
00503         
00504         coarsened = generateJoinMultiBlockLattice<T,Descriptor>(*tmp, *lattices[iLevel-1]);
00505         // make all the dynamics from refinement disappear
00506         defineDynamics<T,Descriptor>(*coarsened, coarsened->getBoundingBox(), 
00507                                      lattices[iLevel-1]->getBackgroundDynamics().clone() );
00508         
00509         // copy from reshaped iLevel to result
00510         copyNonLocal<T,Descriptor>(*tmp, *coarsened, coarsened->getBoundingBox(),modif::staticVariables);
00511         // copy from iLevel-1 to result
00512         copyNonLocal<T,Descriptor>(*lattices[iLevel-1], *coarsened, coarsened->getBoundingBox(),modif::staticVariables);
00513     }
00514     
00515     // final copies
00516     copyNonLocal<T,Descriptor>(*refined, *result, result->getBoundingBox(),modif::staticVariables);
00517     copyNonLocal<T,Descriptor>(*lattices[level], *result, result->getBoundingBox(),modif::staticVariables);
00518     copyNonLocal<T,Descriptor>(*coarsened, *result, result->getBoundingBox(),modif::staticVariables);
00519     
00520     return result;
00521 }
00522 
00524 
00525 template<typename T, template<typename U> class Descriptor>
00526 double getStoredAverageDensity(MultiGridLattice2D<T,Descriptor> const& multiGrid){
00527     return Descriptor<T>::fullRho (
00528                  multiGrid.getInternalStatistics().getAverage(
00529                     LatticeStatistics::avRhoBar ) );
00530 }
00531 
00532 template<typename T, template<typename U> class Descriptor>
00533 double getStoredAverageEnergy(MultiGridLattice2D<T,Descriptor> const& multiGrid){
00534     return 0.5 * multiGrid.getInternalStatistics().getAverage(
00535                                             LatticeStatistics::avUSqr );
00536 }
00537 
00538 template<typename T, template<typename U> class Descriptor>
00539 double getStoredMaxVelocity(MultiGridLattice2D<T,Descriptor> const& multiGrid){
00540     return std::sqrt( multiGrid.getInternalStatistics().getMax (
00541                                LatticeStatistics::maxUSqr ) );
00542 }
00543 
00544 
00545 }// namespace plb
00546 
00547 #endif  // MULTI_GRID_LATTICE_2D_HH