|
Palabos
Version 1.0
|
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 00028 #ifndef BLOCK_LATTICE_2D_HH 00029 #define BLOCK_LATTICE_2D_HH 00030 00031 #include "atomicBlock/blockLattice2D.h" 00032 #include "core/dynamics.h" 00033 #include "core/cell.h" 00034 #include "latticeBoltzmann/latticeTemplates.h" 00035 #include "latticeBoltzmann/indexTemplates.h" 00036 #include "core/util.h" 00037 #include "core/latticeStatistics.h" 00038 #include "core/dynamicsIdentifiers.h" 00039 #include "core/plbProfiler.h" 00040 #include <algorithm> 00041 #include <typeinfo> 00042 #include <cmath> 00043 00044 namespace plb { 00045 00047 00051 template<typename T, template<typename U> class Descriptor> 00052 BlockLattice2D<T,Descriptor>::BlockLattice2D ( 00053 plint nx_, plint ny_, 00054 Dynamics<T,Descriptor>* backgroundDynamics_ ) 00055 : AtomicBlock2D(nx_, ny_), 00056 backgroundDynamics(backgroundDynamics_), 00057 dataTransfer(*this) 00058 { 00059 plint nx = this->getNx(); 00060 plint ny = this->getNy(); 00061 // Allocate memory and attribute dynamics. 00062 allocateAndInitialize(); 00063 for (plint iX=0; iX<nx; ++iX) { 00064 for (plint iY=0; iY<ny; ++iY) { 00065 grid[iX][iY].attributeDynamics(backgroundDynamics); 00066 } 00067 } 00068 // Attribute default value to the standard statistics (average uSqr, 00069 // max uSqr, average rho). These have previously been subscribed 00070 // in the constructor of BlockLatticeBase2D. 00071 std::vector<double> average, sum, max; 00072 std::vector<plint> intSum; 00073 average.push_back(Descriptor<double>::rhoBar((T)1)); 00074 // default average rho to 1, to avoid division by 00075 // zero in constRhoBGK and related models 00076 average.push_back(0.); // default average uSqr to 0 00077 max.push_back(0.); // default max uSqr to 0 00078 plint numCells = 1; // pretend fictitious cell to evaluate statistics 00079 this->getInternalStatistics().evaluate (average, sum, max, intSum, numCells); 00080 } 00081 00086 template<typename T, template<typename U> class Descriptor> 00087 BlockLattice2D<T,Descriptor>::~BlockLattice2D() 00088 { 00089 releaseMemory(); 00090 } 00091 00097 template<typename T, template<typename U> class Descriptor> 00098 BlockLattice2D<T,Descriptor>::BlockLattice2D(BlockLattice2D<T,Descriptor> const& rhs) 00099 : BlockLatticeBase2D<T,Descriptor>(rhs), 00100 AtomicBlock2D(rhs), 00101 backgroundDynamics(rhs.backgroundDynamics->clone()), 00102 dataTransfer(*this) 00103 { 00104 plint nx = this->getNx(); 00105 plint ny = this->getNy(); 00106 allocateAndInitialize(); 00107 for (plint iX=0; iX<nx; ++iX) { 00108 for (plint iY=0; iY<ny; ++iY) { 00109 Cell<T,Descriptor>& cell = grid[iX][iY]; 00110 // Assign cell from rhs 00111 cell = rhs.grid[iX][iY]; 00112 // Get an independent clone of the dynamics, 00113 // or assign backgroundDynamics 00114 if (&cell.getDynamics()==rhs.backgroundDynamics) { 00115 cell.attributeDynamics(backgroundDynamics); 00116 } 00117 else { 00118 cell.attributeDynamics(cell.getDynamics().clone()); 00119 } 00120 } 00121 } 00122 } 00123 00130 template<typename T, template<typename U> class Descriptor> 00131 BlockLattice2D<T,Descriptor>& BlockLattice2D<T,Descriptor>::operator= ( 00132 BlockLattice2D<T,Descriptor> const& rhs ) 00133 { 00134 BlockLattice2D<T,Descriptor> tmp(rhs); 00135 swap(tmp); 00136 return *this; 00137 } 00138 00142 template<typename T, template<typename U> class Descriptor> 00143 void BlockLattice2D<T,Descriptor>::swap(BlockLattice2D& rhs) { 00144 BlockLatticeBase2D<T,Descriptor>::swap(rhs); 00145 AtomicBlock2D::swap(rhs); 00146 std::swap(backgroundDynamics, rhs.backgroundDynamics); 00147 std::swap(rawData, rhs.rawData); 00148 std::swap(grid, rhs.grid); 00149 } 00150 00151 template<typename T, template<typename U> class Descriptor> 00152 void BlockLattice2D<T,Descriptor>::specifyStatisticsStatus ( 00153 Box2D domain, bool status ) 00154 { 00155 // Make sure domain is contained within current lattice 00156 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00157 00158 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00159 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00160 grid[iX][iY].specifyStatisticsStatus(status); 00161 } 00162 } 00163 } 00164 00165 template<typename T, template<typename U> class Descriptor> 00166 void BlockLattice2D<T,Descriptor>::collide(Box2D domain) { 00167 PLB_PRECONDITION( (plint)Descriptor<T>::q==(plint)Descriptor<T>::numPop ); 00168 // Make sure domain is contained within current lattice 00169 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00170 00171 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00172 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00173 grid[iX][iY].collide(this->getInternalStatistics()); 00174 grid[iX][iY].revert(); 00175 } 00176 } 00177 } 00178 00180 template<typename T, template<typename U> class Descriptor> 00181 void BlockLattice2D<T,Descriptor>::collide() { 00182 collide(this->getBoundingBox()); 00183 } 00184 00194 template<typename T, template<typename U> class Descriptor> 00195 void BlockLattice2D<T,Descriptor>::stream(Box2D domain) { 00196 // Make sure domain is contained within current lattice 00197 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00198 00199 static const plint vicinity = Descriptor<T>::vicinity; 00200 00201 bulkStream( Box2D(domain.x0+vicinity,domain.x1-vicinity, 00202 domain.y0+vicinity,domain.y1-vicinity) ); 00203 00204 boundaryStream(domain, Box2D(domain.x0,domain.x0+vicinity-1, 00205 domain.y0,domain.y1)); 00206 boundaryStream(domain, Box2D(domain.x1-vicinity+1,domain.x1, 00207 domain.y0,domain.y1)); 00208 boundaryStream(domain, Box2D(domain.x0+vicinity,domain.x1-vicinity, 00209 domain.y0,domain.y0+vicinity-1)); 00210 boundaryStream(domain, Box2D(domain.x0+vicinity,domain.x1-vicinity, 00211 domain.y1-vicinity+1,domain.y1)); 00212 } 00213 00218 template<typename T, template<typename U> class Descriptor> 00219 void BlockLattice2D<T,Descriptor>::stream() 00220 { 00221 stream(this->getBoundingBox()); 00222 00223 implementPeriodicity(); 00224 00225 this->executeInternalProcessors(); 00226 this->evaluateStatistics(); 00227 this->incrementTime(); 00228 } 00229 00239 template<typename T, template<typename U> class Descriptor> 00240 void BlockLattice2D<T,Descriptor>::collideAndStream(Box2D domain) 00241 { 00242 PLB_PRECONDITION( (plint)Descriptor<T>::q==(plint)Descriptor<T>::numPop ); 00243 // Make sure domain is contained within current lattice 00244 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00245 00246 global::profiler().start("collStream"); 00247 global::profiler().increment("collStreamCells", domain.nCells()); 00248 00249 static const plint vicinity = Descriptor<T>::vicinity; 00250 00251 // First, do the collision on cells within a boundary envelope of width 00252 // equal to the range of the lattice vectors (e.g. 1 for D2Q9) 00253 collide(Box2D(domain.x0,domain.x0+vicinity-1, domain.y0,domain.y1)); 00254 collide(Box2D(domain.x1-vicinity+1,domain.x1, domain.y0,domain.y1)); 00255 collide(Box2D(domain.x0+vicinity,domain.x1-vicinity, domain.y0,domain.y0+vicinity-1)); 00256 collide(Box2D(domain.x0+vicinity,domain.x1-vicinity, domain.y1-vicinity+1,domain.y1)); 00257 00258 // Then, do the efficient collideAndStream algorithm in the bulk, 00259 // excluding the envelope (this is efficient because there is no 00260 // if-then-else statement within the loop, given that the boundary 00261 // region is excluded) 00262 bulkCollideAndStream(Box2D(domain.x0+vicinity,domain.x1-vicinity, 00263 domain.y0+vicinity,domain.y1-vicinity)); 00264 00265 // Finally, do streaming in the boundary envelope to conclude the 00266 // collision-stream cycle 00267 boundaryStream(domain, Box2D(domain.x0,domain.x0+vicinity-1, 00268 domain.y0,domain.y1)); 00269 boundaryStream(domain, Box2D(domain.x1-vicinity+1,domain.x1, 00270 domain.y0,domain.y1)); 00271 boundaryStream(domain, Box2D(domain.x0+vicinity,domain.x1-vicinity, 00272 domain.y0,domain.y0+vicinity-1)); 00273 boundaryStream(domain, Box2D(domain.x0+vicinity,domain.x1-vicinity, 00274 domain.y1-vicinity+1,domain.y1)); 00275 global::profiler().stop("collStream"); 00276 } 00277 00281 template<typename T, template<typename U> class Descriptor> 00282 void BlockLattice2D<T,Descriptor>::collideAndStream() { 00283 collideAndStream(this->getBoundingBox()); 00284 00285 implementPeriodicity(); 00286 00287 this->executeInternalProcessors(); 00288 this->evaluateStatistics(); 00289 this->incrementTime(); 00290 } 00291 00292 template<typename T, template<typename U> class Descriptor> 00293 void BlockLattice2D<T,Descriptor>::incrementTime() { 00294 this->getTimeCounter().incrementTime(); 00295 } 00296 00297 template<typename T, template<typename U> class Descriptor> 00298 void BlockLattice2D<T,Descriptor>::allocateAndInitialize() { 00299 this->getInternalStatistics().subscribeAverage(); // Subscribe average rho-bar 00300 this->getInternalStatistics().subscribeAverage(); // Subscribe average uSqr 00301 this->getInternalStatistics().subscribeMax(); // Subscribe max uSqr 00302 plint nx = this->getNx(); 00303 plint ny = this->getNy(); 00304 rawData = new Cell<T,Descriptor> [nx*ny]; 00305 grid = new Cell<T,Descriptor>* [nx]; 00306 for (plint iX=0; iX<nx; ++iX) { 00307 grid[iX] = rawData + iX*ny; 00308 } 00309 } 00310 00311 template<typename T, template<typename U> class Descriptor> 00312 void BlockLattice2D<T,Descriptor>::releaseMemory() { 00313 plint nx = this->getNx(); 00314 plint ny = this->getNy(); 00315 for (plint iX=0; iX<nx; ++iX) { 00316 for (plint iY=0; iY<ny; ++iY) { 00317 Dynamics<T,Descriptor>* dynamics = &grid[iX][iY].getDynamics(); 00318 if (dynamics != backgroundDynamics) { 00319 delete dynamics; 00320 } 00321 } 00322 } 00323 delete backgroundDynamics; 00324 delete [] rawData; 00325 delete [] grid; 00326 } 00327 00328 template<typename T, template<typename U> class Descriptor> 00329 void BlockLattice2D<T,Descriptor>::attributeDynamics(plint iX, plint iY, Dynamics<T,Descriptor>* dynamics) { 00330 Dynamics<T,Descriptor>* previousDynamics = &grid[iX][iY].getDynamics(); 00331 if (previousDynamics != backgroundDynamics) { 00332 delete previousDynamics; 00333 } 00334 grid[iX][iY].attributeDynamics(dynamics); 00335 } 00336 00337 template<typename T, template<typename U> class Descriptor> 00338 Dynamics<T,Descriptor>& BlockLattice2D<T,Descriptor>::getBackgroundDynamics() { 00339 return *backgroundDynamics; 00340 } 00341 00342 template<typename T, template<typename U> class Descriptor> 00343 Dynamics<T,Descriptor> const& BlockLattice2D<T,Descriptor>::getBackgroundDynamics() const { 00344 return *backgroundDynamics; 00345 } 00346 00353 template<typename T, template<typename U> class Descriptor> 00354 void BlockLattice2D<T,Descriptor>::boundaryStream(Box2D bound, Box2D domain) { 00355 // Make sure bound is contained within current lattice 00356 PLB_PRECONDITION( contained(bound, this->getBoundingBox()) ); 00357 // Make sure domain is contained within bound 00358 PLB_PRECONDITION( contained(domain, bound) ); 00359 00360 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00361 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00362 for (plint iPop=1; iPop<=Descriptor<T>::q/2; ++iPop) { 00363 plint nextX = iX + Descriptor<T>::c[iPop][0]; 00364 plint nextY = iY + Descriptor<T>::c[iPop][1]; 00365 if (nextX>=bound.x0 && nextX<=bound.x1 && nextY>=bound.y0 && nextY<=bound.y1) { 00366 std::swap(grid[iX][iY][iPop+Descriptor<T>::q/2], 00367 grid[nextX][nextY][iPop]); 00368 } 00369 } 00370 } 00371 } 00372 } 00373 00379 template<typename T, template<typename U> class Descriptor> 00380 void BlockLattice2D<T,Descriptor>::bulkStream(Box2D domain) { 00381 // Make sure domain is contained within current lattice 00382 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00383 00384 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00385 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00386 for (plint iPop=1; iPop<=Descriptor<T>::q/2; ++iPop) { 00387 plint nextX = iX + Descriptor<T>::c[iPop][0]; 00388 plint nextY = iY + Descriptor<T>::c[iPop][1]; 00389 std::swap(grid[iX][iY][iPop+Descriptor<T>::q/2], 00390 grid[nextX][nextY][iPop]); 00391 } 00392 } 00393 } 00394 } 00395 00401 template<typename T, template<typename U> class Descriptor> 00402 void BlockLattice2D<T,Descriptor>::bulkCollideAndStream(Box2D domain) { 00403 // Make sure domain is contained within current lattice 00404 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00405 00406 if (Descriptor<T>::vicinity==1) { 00407 // On nearest-neighbor lattice, use the cache-efficient 00408 // version of collidAndStream. 00409 blockwiseBulkCollideAndStream(domain); 00410 } 00411 else { 00412 // Otherwise, use the straightforward implementation. 00413 // Note that at some point, we should implement the cache-efficient 00414 // version for extended lattices as well. 00415 linearBulkCollideAndStream(domain); 00416 } 00417 } 00418 00419 00423 template<typename T, template<typename U> class Descriptor> 00424 void BlockLattice2D<T,Descriptor>::linearBulkCollideAndStream(Box2D domain) { 00425 // Make sure domain is contained within current lattice 00426 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00427 00428 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00429 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00430 grid[iX][iY].collide(this->getInternalStatistics()); 00431 latticeTemplates<T,Descriptor>::swapAndStream2D(grid, iX, iY); 00432 } 00433 } 00434 } 00435 00436 00441 template<typename T, template<typename U> class Descriptor> 00442 void BlockLattice2D<T,Descriptor>::blockwiseBulkCollideAndStream(Box2D domain) { 00443 // Make sure domain is contained within current lattice 00444 PLB_PRECONDITION( contained(domain, this->getBoundingBox()) ); 00445 00446 // For cache efficiency, memory is traversed block-wise. The two outer loops enumerate 00447 // the blocks, whereas the two inner loops enumerate the cells inside each block. 00448 const plint blockSize = cachePolicy().getBlockSize(); 00449 // Outer loops. 00450 for (plint outerX=domain.x0; outerX<=domain.x1; outerX+=blockSize) { 00451 for (plint outerY=domain.y0; outerY<=domain.y1+blockSize-1; outerY+=blockSize) { 00452 // Inner loops. 00453 plint dx = 0; 00454 for (plint innerX=outerX; 00455 innerX <= std::min(outerX+blockSize-1, domain.x1); 00456 ++innerX, ++dx) 00457 { 00458 // Y-index is shifted in negative direction at each x-increment. to ensure 00459 // that only post-collision cells are accessed during the swap-operation 00460 // of the streaming. 00461 plint minY = outerY-dx; 00462 plint maxY = minY+blockSize-1; 00463 for (plint innerY=std::max(minY,domain.y0); 00464 innerY <= std::min(maxY, domain.y1); 00465 ++innerY) 00466 { 00467 // Collide the cell. 00468 grid[innerX][innerY].collide ( 00469 this->getInternalStatistics() ); 00470 // Swap the populations on the cell, and then with post-collision 00471 // neighboring cell, to perform the streaming step. 00472 latticeTemplates<T,Descriptor>::swapAndStream2D ( 00473 grid, innerX, innerY ); 00474 } 00475 } 00476 } 00477 } 00478 } 00479 00480 template<typename T, template<typename U> class Descriptor> 00481 void BlockLattice2D<T,Descriptor>::periodicDomain(Box2D domain) { 00482 plint nx = this->getNx(); 00483 plint ny = this->getNy(); 00484 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00485 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00486 for (plint iPop=1; iPop<Descriptor<T>::q; ++iPop) { 00487 plint prevX = iX - Descriptor<T>::c[iPop][0]; 00488 plint prevY = iY - Descriptor<T>::c[iPop][1]; 00489 if ( (prevX>=0 && prevX<nx) && 00490 (prevY>=0 && prevY<ny) ) 00491 { 00492 plint nextX = (iX+nx)%nx; 00493 plint nextY = (iY+ny)%ny; 00494 std::swap ( 00495 grid[prevX][prevY][indexTemplates::opposite<Descriptor<T> >(iPop)], 00496 grid[nextX][nextY][iPop] ); 00497 } 00498 } 00499 } 00500 } 00501 } 00502 00503 template<typename T, template<typename U> class Descriptor> 00504 void BlockLattice2D<T,Descriptor>::implementPeriodicity() { 00505 static const plint vicinity = Descriptor<T>::vicinity; 00506 plint maxX = this->getNx()-1; 00507 plint maxY = this->getNy()-1; 00508 // Periodicity of edges orthogonal to x-axis. 00509 periodicDomain(Box2D(-vicinity,-1,0,maxY)); 00510 // Periodicity of edges orthogonal to y-axis. 00511 periodicDomain(Box2D(0,maxX,-vicinity,-1)); 00512 // Periodicity between (-1,-1) and (+1,+1) corner. 00513 periodicDomain(Box2D(-vicinity,-1,-vicinity,-1)); 00514 // Periodicity between (-1,+1) and (+1,-1) corner. 00515 periodicDomain(Box2D(-vicinity,-1,maxY+1,maxY+vicinity)); 00516 } 00517 00518 template<typename T, template<typename U> class Descriptor> 00519 BlockLatticeDataTransfer2D<T,Descriptor>& BlockLattice2D<T,Descriptor>::getDataTransfer() { 00520 return dataTransfer; 00521 } 00522 00523 template<typename T, template<typename U> class Descriptor> 00524 BlockLatticeDataTransfer2D<T,Descriptor> const& BlockLattice2D<T,Descriptor>::getDataTransfer() const { 00525 return dataTransfer; 00526 } 00527 00528 00530 00531 template<typename T, template<typename U> class Descriptor> 00532 BlockLatticeDataTransfer2D<T,Descriptor>::BlockLatticeDataTransfer2D(BlockLattice2D<T,Descriptor>& lattice_) 00533 : lattice(lattice_) 00534 { } 00535 00536 template<typename T, template<typename U> class Descriptor> 00537 plint BlockLatticeDataTransfer2D<T,Descriptor>::staticCellSize() const { 00538 return sizeof(T)* (Descriptor<T>::numPop + Descriptor<T>::ExternalField::numScalars); 00539 } 00540 00541 template<typename T, template<typename U> class Descriptor> 00542 void BlockLatticeDataTransfer2D<T,Descriptor>::send ( 00543 Box2D domain, std::vector<char>& buffer, modif::ModifT kind ) const 00544 { 00545 PLB_PRECONDITION(contained(domain, lattice.getBoundingBox())); 00546 // It's the responsibility of the functions called below to allocate 00547 // the right amount of memory for the buffer. 00548 buffer.clear(); 00549 switch(kind) { 00550 case modif::staticVariables: 00551 send_static(domain, buffer); break; 00552 case modif::dynamicVariables: 00553 send_dynamic(domain, buffer); break; 00554 // Serialization is the same no matter if the dynamics object 00555 // is being regenerated or not by the recipient. 00556 case modif::allVariables: 00557 case modif::dataStructure: 00558 send_all(domain,buffer); break; 00559 default: PLB_ASSERT(false); 00560 } 00561 } 00562 00563 template<typename T, template<typename U> class Descriptor> 00564 void BlockLatticeDataTransfer2D<T,Descriptor>::send_static ( 00565 Box2D domain, std::vector<char>& buffer ) const 00566 { 00567 plint cellSize = staticCellSize(); 00568 pluint numBytes = domain.nCells()*cellSize; 00569 // Avoid dereferencing uninitialized pointer. 00570 if (numBytes==0) return; 00571 buffer.resize(numBytes); 00572 00573 plint iData=0; 00574 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00575 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00576 lattice.get(iX,iY).serialize(&buffer[iData]); 00577 iData += cellSize; 00578 } 00579 } 00580 } 00581 00582 template<typename T, template<typename U> class Descriptor> 00583 void BlockLatticeDataTransfer2D<T,Descriptor>::send_dynamic ( 00584 Box2D domain, std::vector<char>& buffer ) const 00585 { 00586 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00587 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00588 // The serialize function automatically reallocates memory for buffer. 00589 serialize(lattice.get(iX,iY).getDynamics(), buffer); 00590 } 00591 } 00592 } 00593 00594 template<typename T, template<typename U> class Descriptor> 00595 void BlockLatticeDataTransfer2D<T,Descriptor>::send_all ( 00596 Box2D domain, std::vector<char>& buffer ) const 00597 { 00598 plint cellSize = staticCellSize(); 00599 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00600 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00601 // 1. Send dynamic info (automaic allocation of buffer memory). 00602 serialize(lattice.get(iX,iY).getDynamics(), buffer); 00603 pluint pos = buffer.size(); 00604 // 2. Send static info (needs manual allocation of buffer memory). 00605 if (staticCellSize()>0) { 00606 buffer.resize(pos+cellSize); 00607 lattice.get(iX,iY).serialize(&buffer[pos]); 00608 } 00609 } 00610 } 00611 } 00612 00613 template<typename T, template<typename U> class Descriptor> 00614 void BlockLatticeDataTransfer2D<T,Descriptor>::receive ( 00615 Box2D domain, std::vector<char> const& buffer, 00616 modif::ModifT kind, std::map<int,std::string> const& foreignIds ) 00617 { 00618 if (kind==modif::dataStructure && !foreignIds.empty()) { 00619 std::map<int,int> idIndirect; 00620 meta::createIdIndirection<T,Descriptor>(foreignIds, idIndirect); 00621 receive_regenerate(domain, buffer, idIndirect); 00622 } 00623 else { 00624 receive(domain, buffer, kind); 00625 } 00626 } 00627 00628 template<typename T, template<typename U> class Descriptor> 00629 void BlockLatticeDataTransfer2D<T,Descriptor>::receive ( 00630 Box2D domain, std::vector<char> const& buffer, modif::ModifT kind ) 00631 { 00632 PLB_PRECONDITION(contained(domain, lattice.getBoundingBox())); 00633 switch(kind) { 00634 case modif::staticVariables: 00635 receive_static(domain, buffer); break; 00636 case modif::dynamicVariables: 00637 receive_dynamic(domain, buffer); break; 00638 case modif::allVariables: 00639 receive_all(domain, buffer); break; 00640 case modif::dataStructure: 00641 receive_regenerate(domain, buffer); break; 00642 default: 00643 PLB_ASSERT( false ); 00644 } 00645 } 00646 00647 template<typename T, template<typename U> class Descriptor> 00648 void BlockLatticeDataTransfer2D<T,Descriptor>::receive_static ( 00649 Box2D domain, std::vector<char> const& buffer ) 00650 { 00651 PLB_PRECONDITION( (plint) buffer.size() == domain.nCells()*staticCellSize() ); 00652 // Avoid dereferencing uninitialized pointer. 00653 if (buffer.empty()) return; 00654 plint cellSize = staticCellSize(); 00655 00656 // All serialized data if of type T; therefore, buffer is considered 00657 // as being a T-array right away. 00658 plint iData=0; 00659 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00660 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00661 lattice.get(iX,iY).unSerialize(&buffer[iData]); 00662 iData += cellSize; 00663 } 00664 } 00665 } 00666 00667 template<typename T, template<typename U> class Descriptor> 00668 void BlockLatticeDataTransfer2D<T,Descriptor>::receive_dynamic ( 00669 Box2D domain, std::vector<char> const& buffer ) 00670 { 00671 pluint serializerPos = 0; 00672 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00673 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00674 // No assert is included here, because incompatible types of 00675 // dynamics are detected by asserts inside HierarchicUnserializer. 00676 serializerPos = 00677 unserialize ( 00678 lattice.get(iX,iY).getDynamics(), buffer, serializerPos ); 00679 } 00680 } 00681 } 00682 00683 template<typename T, template<typename U> class Descriptor> 00684 void BlockLatticeDataTransfer2D<T,Descriptor>::receive_all ( 00685 Box2D domain, std::vector<char> const& buffer ) 00686 { 00687 pluint posInBuffer = 0; 00688 plint cellSize = staticCellSize(); 00689 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00690 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00691 // 1. Unserialize dynamic data. 00692 posInBuffer = 00693 unserialize ( 00694 lattice.get(iX,iY).getDynamics(), buffer, posInBuffer ); 00695 // 2. Unserialize static data. 00696 if (staticCellSize()>0) { 00697 lattice.get(iX,iY).unSerialize(&buffer[posInBuffer]); 00698 posInBuffer += cellSize; 00699 } 00700 } 00701 } 00702 } 00703 00704 template<typename T, template<typename U> class Descriptor> 00705 void BlockLatticeDataTransfer2D<T,Descriptor>::receive_regenerate ( 00706 Box2D domain, std::vector<char> const& buffer, std::map<int,int> const& idIndirect ) 00707 { 00708 pluint posInBuffer = 0; 00709 plint cellSize = staticCellSize(); 00710 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00711 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00712 // 1. Generate dynamics object, and unserialize dynamic data. 00713 std::map<int,int> const* indirectPtr = idIndirect.empty() ? 0 : &idIndirect; 00714 HierarchicUnserializer unserializer(buffer, posInBuffer, indirectPtr); 00715 Dynamics<T,Descriptor>* newDynamics = 00716 meta::dynamicsRegistration<T,Descriptor>().generate(unserializer); 00717 posInBuffer = unserializer.getCurrentPos(); 00718 lattice.attributeDynamics(iX,iY, newDynamics); 00719 00720 // 2. Unserialize static data. 00721 if (staticCellSize()>0) { 00722 PLB_ASSERT( !buffer.empty() ); 00723 PLB_ASSERT( posInBuffer+staticCellSize()<=buffer.size() ); 00724 lattice.get(iX,iY).unSerialize(&buffer[posInBuffer]); 00725 posInBuffer += cellSize; 00726 } 00727 } 00728 } 00729 } 00730 00731 template<typename T, template<typename U> class Descriptor> 00732 void BlockLatticeDataTransfer2D<T,Descriptor>::attribute ( 00733 Box2D toDomain, plint deltaX, plint deltaY, 00734 AtomicBlock2D const& from, modif::ModifT kind ) 00735 { 00736 PLB_PRECONDITION (typeid(from) == typeid(BlockLattice2D<T,Descriptor> const&)); 00737 PLB_PRECONDITION(contained(toDomain, lattice.getBoundingBox())); 00738 BlockLattice2D<T,Descriptor> const& fromLattice = (BlockLattice2D<T,Descriptor> const&) from; 00739 switch(kind) { 00740 case modif::staticVariables: 00741 attribute_static(toDomain, deltaX, deltaY, fromLattice); break; 00742 case modif::dynamicVariables: 00743 attribute_dynamic(toDomain, deltaX, deltaY, fromLattice); break; 00744 case modif::allVariables: 00745 attribute_all(toDomain, deltaX, deltaY, fromLattice); break; 00746 case modif::dataStructure: 00747 attribute_regenerate(toDomain, deltaX, deltaY, fromLattice); break; 00748 default: 00749 PLB_ASSERT( false ); 00750 } 00751 } 00752 00753 template<typename T, template<typename U> class Descriptor> 00754 void BlockLatticeDataTransfer2D<T,Descriptor>::attribute_static ( 00755 Box2D toDomain, plint deltaX, plint deltaY, 00756 BlockLattice2D<T,Descriptor> const& from ) 00757 { 00758 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00759 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00760 lattice.get(iX,iY).attributeValues ( 00761 from.get(iX+deltaX,iY+deltaY) ); 00762 } 00763 } 00764 } 00765 00766 template<typename T, template<typename U> class Descriptor> 00767 void BlockLatticeDataTransfer2D<T,Descriptor>::attribute_dynamic ( 00768 Box2D toDomain, plint deltaX, plint deltaY, 00769 BlockLattice2D<T,Descriptor> const& from ) 00770 { 00771 std::vector<char> serializedData; 00772 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00773 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00774 serializedData.clear(); 00775 serialize ( 00776 from.get(iX+deltaX,iY+deltaY).getDynamics(), 00777 serializedData ); 00778 unserialize ( 00779 lattice.get(iX,iY).getDynamics(), 00780 serializedData ); 00781 } 00782 } 00783 } 00784 00785 template<typename T, template<typename U> class Descriptor> 00786 void BlockLatticeDataTransfer2D<T,Descriptor>::attribute_all ( 00787 Box2D toDomain, plint deltaX, plint deltaY, 00788 BlockLattice2D<T,Descriptor> const& from ) 00789 { 00790 std::vector<char> serializedData; 00791 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00792 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00793 // 1. Attribute dynamic content. 00794 serializedData.clear(); 00795 serialize ( 00796 from.get(iX+deltaX,iY+deltaY).getDynamics(), 00797 serializedData ); 00798 unserialize ( 00799 lattice.get(iX,iY).getDynamics(), 00800 serializedData ); 00801 00802 // 2. Attribute static content. 00803 lattice.get(iX,iY).attributeValues ( 00804 from.get(iX+deltaX,iY+deltaY) ); 00805 } 00806 } 00807 } 00808 00809 template<typename T, template<typename U> class Descriptor> 00810 void BlockLatticeDataTransfer2D<T,Descriptor>::attribute_regenerate ( 00811 Box2D toDomain, plint deltaX, plint deltaY, 00812 BlockLattice2D<T,Descriptor> const& from ) 00813 { 00814 std::vector<char> serializedData; 00815 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00816 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00817 // 1. Generate new dynamics and attribute dynamic content. 00818 serializedData.clear(); 00819 serialize ( 00820 from.get(iX+deltaX,iY+deltaY).getDynamics(), 00821 serializedData ); 00822 HierarchicUnserializer unserializer(serializedData, 0); 00823 Dynamics<T,Descriptor>* newDynamics = 00824 meta::dynamicsRegistration<T,Descriptor>().generate(unserializer); 00825 lattice.attributeDynamics(iX,iY, newDynamics); 00826 00827 // 2. Attribute static content. 00828 lattice.get(iX,iY).attributeValues ( 00829 from.get(iX+deltaX,iY+deltaY) ); 00830 } 00831 } 00832 } 00833 00834 template<typename T, template<typename U> class Descriptor> 00835 CachePolicy2D& BlockLattice2D<T,Descriptor>::cachePolicy() { 00836 static CachePolicy2D cachePolicySingleton(200); 00837 return cachePolicySingleton; 00838 } 00839 00840 00842 00843 template<typename T, template<typename U> class Descriptor> 00844 double getStoredAverageDensity(BlockLattice2D<T,Descriptor> const& blockLattice) { 00845 return Descriptor<T>::fullRho ( 00846 blockLattice.getInternalStatistics().getAverage ( 00847 LatticeStatistics::avRhoBar ) ); 00848 } 00849 00850 template<typename T, template<typename U> class Descriptor> 00851 double getStoredAverageEnergy(BlockLattice2D<T,Descriptor> const& blockLattice) { 00852 return 0.5 * blockLattice.getInternalStatistics().getAverage ( 00853 LatticeStatistics::avUSqr ); 00854 } 00855 00856 template<typename T, template<typename U> class Descriptor> 00857 double getStoredMaxVelocity(BlockLattice2D<T,Descriptor> const& blockLattice) { 00858 return std::sqrt( blockLattice.getInternalStatistics().getMax ( 00859 LatticeStatistics::maxUSqr ) ); 00860 } 00861 00862 } // namespace plb 00863 00864 #endif // BLOCK_LATTICE_2D_HH