|
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 00029 #ifndef DATA_FIELD_2D_HH 00030 #define DATA_FIELD_2D_HH 00031 00032 #include "atomicBlock/dataField2D.h" 00033 #include "atomicBlock/atomicBlock2D.h" 00034 #include <algorithm> 00035 #include <typeinfo> 00036 #include <cstring> 00037 00038 namespace plb { 00039 00041 00042 template<typename T> 00043 ScalarField2D<T>::ScalarField2D(plint nx_, plint ny_, T iniVal) 00044 : AtomicBlock2D(nx_, ny_), 00045 dataTransfer(*this) 00046 { 00047 allocateMemory(); 00048 for (pluint iData=0; iData<getSize(); ++iData) { 00049 (*this)[iData] = iniVal; 00050 } 00051 } 00052 00053 template<typename T> 00054 ScalarField2D<T>::~ScalarField2D() { 00055 releaseMemory(); 00056 } 00057 00058 template<typename T> 00059 ScalarField2D<T>::ScalarField2D(ScalarField2D<T> const& rhs) 00060 : AtomicBlock2D(rhs), 00061 dataTransfer(*this) 00062 { 00063 allocateMemory(); 00064 for (pluint iData=0; iData<getSize(); ++iData) { 00065 (*this)[iData] = rhs[iData]; 00066 } 00067 } 00068 00069 template<typename T> 00070 ScalarField2D<T>& ScalarField2D<T>::operator=(ScalarField2D<T> const& rhs) { 00071 ScalarField2D<T> tmp(rhs); 00072 swap(tmp); 00073 return *this; 00074 } 00075 00076 template<typename T> 00077 void ScalarField2D<T>::swap(ScalarField2D<T>& rhs) { 00078 AtomicBlock2D::swap(rhs); 00079 std::swap(rawData, rhs.rawData); 00080 std::swap(field, rhs.field); 00081 } 00082 00083 00084 template<typename T> 00085 void ScalarField2D<T>::reset() { 00086 for (plint index=0; index<this->getNx()*this->getNy(); ++index) { 00087 (*this)[index] = T(); 00088 } 00089 } 00090 00091 template<typename T> 00092 ScalarFieldDataTransfer2D<T>& ScalarField2D<T>::getDataTransfer() { 00093 return dataTransfer; 00094 } 00095 00096 template<typename T> 00097 ScalarFieldDataTransfer2D<T> const& ScalarField2D<T>::getDataTransfer() const { 00098 return dataTransfer; 00099 } 00100 00101 template<typename T> 00102 void ScalarField2D<T>::allocateMemory() { 00103 rawData = new T[(pluint)this->getNx()*(pluint)this->getNy()]; 00104 field = new T* [(pluint)this->getNx()]; 00105 for (plint iX=0; iX<this->getNx(); ++iX) { 00106 field[iX] = rawData + (pluint)iX*(pluint)this->getNy(); 00107 } 00108 } 00109 00110 template<typename T> 00111 void ScalarField2D<T>::releaseMemory() { 00112 delete [] field; 00113 delete [] rawData; rawData = 0; 00114 } 00115 00117 00118 template<typename T> 00119 ScalarFieldDataTransfer2D<T>::ScalarFieldDataTransfer2D(ScalarField2D<T>& field_) 00120 : field(field_) 00121 { } 00122 00123 template<typename T> 00124 plint ScalarFieldDataTransfer2D<T>::staticCellSize() const { 00125 return sizeof(T); 00126 } 00127 00128 template<typename T> 00129 void ScalarFieldDataTransfer2D<T>::send(Box2D domain, std::vector<char>& buffer, modif::ModifT kind) const 00130 { 00131 PLB_PRECONDITION( contained(domain, field.getBoundingBox()) ); 00132 plint cellSize = staticCellSize(); 00133 pluint numBytes = domain.nCells()*cellSize; 00134 // Avoid dereferencing uninitialized pointer. 00135 if (numBytes==0) return; 00136 buffer.resize(numBytes); 00137 00138 plint iData=0; 00139 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00140 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00141 memcpy((void*)(&buffer[iData]), (const void*)(&field.get(iX,iY)), sizeof(T)); 00142 iData += sizeof(T); 00143 } 00144 } 00145 } 00146 00147 template<typename T> 00148 void ScalarFieldDataTransfer2D<T>::receive ( 00149 Box2D domain, std::vector<char> const& buffer, modif::ModifT kind ) 00150 { 00151 PLB_PRECONDITION( contained(domain, field.getBoundingBox()) ); 00152 PLB_PRECONDITION( domain.nCells()*staticCellSize() == (plint) buffer.size() ); 00153 00154 // Avoid dereferencing uninitialized pointer. 00155 if (buffer.empty()) return; 00156 plint iData=0; 00157 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00158 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00159 memcpy((void*)(&field.get(iX,iY)), (const void*)(&buffer[iData]), sizeof(T)); 00160 iData += sizeof(T); 00161 } 00162 } 00163 } 00164 00165 template<typename T> 00166 void ScalarFieldDataTransfer2D<T>::attribute ( 00167 Box2D toDomain, plint deltaX, plint deltaY, 00168 AtomicBlock2D const& from, modif::ModifT kind ) 00169 { 00170 PLB_PRECONDITION (typeid(from) == typeid(ScalarField2D<T> const&)); 00171 PLB_PRECONDITION( contained(toDomain, field.getBoundingBox()) ); 00172 ScalarField2D<T> const& fromField = (ScalarField2D<T> const&) from; 00173 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00174 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00175 field.get(iX,iY) = fromField.get(iX+deltaX,iY+deltaY); 00176 } 00177 } 00178 } 00179 00180 00182 00183 template<typename T, int nDim> 00184 TensorField2D<T,nDim>::TensorField2D(plint nx_, plint ny_) 00185 : AtomicBlock2D(nx_,ny_), 00186 dataTransfer(*this) 00187 { 00188 allocateMemory(); 00189 for (plint iData=0; iData<this->getNx()*this->getNy(); ++iData) { 00190 for (int iDim=0; iDim<nDim; ++iDim) { 00191 (*this)[iData][iDim] = T(); 00192 } 00193 } 00194 } 00195 00196 template<typename T, int nDim> 00197 TensorField2D<T,nDim>::TensorField2D(plint nx_, plint ny_, Array<T,nDim> const& iniVal) 00198 : AtomicBlock2D(nx_,ny_), 00199 dataTransfer(*this) 00200 { 00201 allocateMemory(); 00202 for (plint iData=0; iData<this->getNx()*this->getNy(); ++iData) { 00203 for (int iDim=0; iDim<nDim; ++iDim) { 00204 (*this)[iData][iDim] = iniVal[iDim]; 00205 } 00206 } 00207 } 00208 00209 template<typename T, int nDim> 00210 TensorField2D<T,nDim>::~TensorField2D() { 00211 releaseMemory(); 00212 } 00213 00214 template<typename T, int nDim> 00215 TensorField2D<T,nDim>::TensorField2D(TensorField2D<T,nDim> const& rhs) 00216 : AtomicBlock2D(rhs), 00217 dataTransfer(*this) 00218 { 00219 allocateMemory(); 00220 for (plint iData=0; iData<this->getNx()*this->getNy(); ++iData) { 00221 for (int iDim=0; iDim<nDim; ++iDim) { 00222 (*this)[iData][iDim] = rhs[iData][iDim]; 00223 } 00224 } 00225 } 00226 00227 template<typename T, int nDim> 00228 TensorField2D<T,nDim>& TensorField2D<T,nDim>::operator=(TensorField2D<T,nDim> const& rhs) { 00229 TensorField2D<T,nDim> tmp(rhs); 00230 swap(tmp); 00231 return *this; 00232 } 00233 00234 template<typename T, int nDim> 00235 void TensorField2D<T,nDim>::swap(TensorField2D<T,nDim>& rhs) { 00236 AtomicBlock2D::swap(rhs); 00237 std::swap(rawData, rhs.rawData); 00238 std::swap(field, rhs.field); 00239 } 00240 00241 template<typename T, int nDim> 00242 void TensorField2D<T,nDim>::reset() { 00243 for (plint index=0; index<this->getNx()*this->getNy(); ++index) { 00244 for (int iDim=0; iDim<nDim; ++iDim) { 00245 (*this)[index][iDim] = T(); 00246 } 00247 } 00248 } 00249 00250 template<typename T, int nDim> 00251 TensorFieldDataTransfer2D<T,nDim>& TensorField2D<T,nDim>::getDataTransfer() { 00252 return dataTransfer; 00253 } 00254 00255 template<typename T, int nDim> 00256 TensorFieldDataTransfer2D<T,nDim> const& TensorField2D<T,nDim>::getDataTransfer() const { 00257 return dataTransfer; 00258 } 00259 00260 template<typename T, int nDim> 00261 void TensorField2D<T,nDim>::allocateMemory() { 00262 rawData = new Array<T,nDim>[(pluint)this->getNx()*(pluint)this->getNy()]; 00263 field = new Array<T,nDim>* [(pluint)this->getNx()]; 00264 for (plint iX=0; iX<this->getNx(); ++iX) { 00265 field[iX] = rawData + (pluint)iX*(pluint)this->getNy(); 00266 } 00267 } 00268 00269 template<typename T, int nDim> 00270 void TensorField2D<T,nDim>::releaseMemory() { 00271 delete [] field; 00272 delete [] rawData; rawData = 0; 00273 } 00274 00276 00277 template<typename T, int nDim> 00278 TensorFieldDataTransfer2D<T,nDim>::TensorFieldDataTransfer2D(TensorField2D<T,nDim>& field_) 00279 : field(field_) 00280 { } 00281 00282 template<typename T, int nDim> 00283 plint TensorFieldDataTransfer2D<T,nDim>::staticCellSize() const { 00284 return nDim*sizeof(T); 00285 } 00286 00287 template<typename T, int nDim> 00288 void TensorFieldDataTransfer2D<T,nDim>::send(Box2D domain, std::vector<char>& buffer, modif::ModifT kind) const 00289 { 00290 PLB_PRECONDITION( contained(domain, field.getBoundingBox()) ); 00291 plint cellSize = staticCellSize(); 00292 pluint numBytes = domain.nCells()*cellSize; 00293 // Avoid dereferencing uninitialized pointer. 00294 if (numBytes==0) return; 00295 buffer.resize(numBytes); 00296 00297 plint iData=0; 00298 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00299 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00300 memcpy((void*)(&buffer[iData]), (const void*)(&field.get(iX,iY)[0]), nDim*sizeof(T)); 00301 iData += nDim*sizeof(T); 00302 } 00303 } 00304 } 00305 00306 template<typename T, int nDim> 00307 void TensorFieldDataTransfer2D<T,nDim>::receive( 00308 Box2D domain, std::vector<char> const& buffer, modif::ModifT kind ) 00309 { 00310 PLB_PRECONDITION( contained(domain, field.getBoundingBox()) ); 00311 PLB_PRECONDITION( domain.nCells()*staticCellSize() == (plint) buffer.size() ); 00312 00313 // Avoid dereferencing uninitialized pointer. 00314 if (buffer.empty()) return; 00315 plint iData=0; 00316 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00317 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00318 memcpy((void*)(&field.get(iX,iY)[0]), (const void*)(&buffer[iData]), nDim*sizeof(T)); 00319 iData += nDim*sizeof(T); 00320 } 00321 } 00322 } 00323 00324 template<typename T, int nDim> 00325 void TensorFieldDataTransfer2D<T,nDim>::attribute ( 00326 Box2D toDomain, plint deltaX, plint deltaY, 00327 AtomicBlock2D const& from, modif::ModifT kind ) 00328 { 00329 PLB_PRECONDITION (typeid(from) == typeid(TensorField2D<T,nDim> const&)); 00330 PLB_PRECONDITION( contained(toDomain, field.getBoundingBox()) ); 00331 TensorField2D<T,nDim> const& fromField = (TensorField2D<T,nDim> const&) from; 00332 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00333 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00334 for (int iDim=0; iDim<nDim; ++iDim) { 00335 field.get(iX,iY)[iDim] = fromField.get(iX+deltaX,iY+deltaY)[iDim]; 00336 } 00337 } 00338 } 00339 } 00340 00342 00343 template<typename T> 00344 NTensorField2D<T>::NTensorField2D(plint nx_, plint ny_, plint ndim_) 00345 : NTensorFieldBase2D<T>(ndim_), 00346 AtomicBlock2D(nx_,ny_), 00347 dataTransfer(*this) 00348 { 00349 allocateMemory(); 00350 reset(); 00351 } 00352 00353 template<typename T> 00354 NTensorField2D<T>::NTensorField2D(plint nx_, plint ny_, plint ndim_, T const* iniVal) 00355 : NTensorFieldBase2D<T>(ndim_), 00356 AtomicBlock2D(nx_,ny_), 00357 dataTransfer(*this) 00358 { 00359 allocateMemory(); 00360 for ( plint iData=0; iData<this->getNx()*this->getNy()*this->getNdim(); 00361 iData+=this->getNdim() ) 00362 { 00363 for (plint iDim=0; iDim<this->getNdim(); ++iDim) 00364 { 00365 (*this)[iData+iDim] = iniVal[iDim]; 00366 } 00367 } 00368 } 00369 00370 template<typename T> 00371 NTensorField2D<T>::~NTensorField2D() { 00372 releaseMemory(); 00373 } 00374 00375 template<typename T> 00376 NTensorField2D<T>::NTensorField2D(NTensorField2D<T> const& rhs) 00377 : NTensorFieldBase2D<T>(rhs), 00378 AtomicBlock2D(rhs), 00379 dataTransfer(*this) 00380 { 00381 allocateMemory(); 00382 for (plint iData=0; iData<this->getNx()*this->getNy()*this->getNdim(); ++iData) { 00383 (*this)[iData] = rhs[iData]; 00384 } 00385 } 00386 00387 template<typename T> 00388 NTensorField2D<T>& NTensorField2D<T>::operator=(NTensorField2D<T> const& rhs) { 00389 NTensorField2D<T> tmp(rhs); 00390 swap(tmp); 00391 return *this; 00392 } 00393 00394 template<typename T> 00395 void NTensorField2D<T>::swap(NTensorField2D<T>& rhs) { 00396 NTensorFieldBase2D<T>::swap(rhs); 00397 AtomicBlock2D::swap(rhs); 00398 std::swap(rawData, rhs.rawData); 00399 std::swap(field, rhs.field); 00400 } 00401 00402 template<typename T> 00403 void NTensorField2D<T>::reset() { 00404 for (plint index=0; index<this->getNx()*this->getNy()*this->getNdim(); ++index) { 00405 (*this)[index] = T(); 00406 } 00407 } 00408 00409 template<typename T> 00410 NTensorFieldDataTransfer2D<T>& NTensorField2D<T>::getDataTransfer() { 00411 return dataTransfer; 00412 } 00413 00414 template<typename T> 00415 NTensorFieldDataTransfer2D<T> const& NTensorField2D<T>::getDataTransfer() const { 00416 return dataTransfer; 00417 } 00418 00419 template<typename T> 00420 void NTensorField2D<T>::allocateMemory() { 00421 rawData = new T[(pluint)this->getNx()*(pluint)this->getNy()*(pluint)this->getNdim()]; 00422 field = new T** [(pluint)this->getNx()]; 00423 for (plint iX=0; iX<this->getNx(); ++iX) { 00424 field[iX] = new T* [(pluint)this->getNy()]; 00425 for (plint iY=0; iY<this->getNy(); ++iY) { 00426 field[iX][iY] = rawData + (pluint)this->getNdim()*((pluint)iY+(pluint)this->getNy()*(pluint)iX); 00427 } 00428 } 00429 } 00430 00431 template<typename T> 00432 void NTensorField2D<T>::releaseMemory() { 00433 for (plint iX=0; iX<this->getNx(); ++iX) { 00434 delete [] field[iX]; 00435 } 00436 delete [] field; 00437 delete [] rawData; rawData = 0; 00438 } 00439 00441 00442 template<typename T> 00443 NTensorFieldDataTransfer2D<T>::NTensorFieldDataTransfer2D(NTensorField2D<T>& field_) 00444 : field(field_) 00445 { } 00446 00447 template<typename T> 00448 plint NTensorFieldDataTransfer2D<T>::staticCellSize() const { 00449 return field.getNdim()*sizeof(T); 00450 } 00451 00452 template<typename T> 00453 void NTensorFieldDataTransfer2D<T>::send(Box2D domain, std::vector<char>& buffer, modif::ModifT kind) const 00454 { 00455 PLB_PRECONDITION( contained(domain, field.getBoundingBox()) ); 00456 plint cellSize = staticCellSize(); 00457 pluint numBytes = domain.nCells()*cellSize; 00458 buffer.resize(numBytes); 00459 00460 plint iData=0; 00461 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00462 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00463 memcpy((void*)(&buffer[iData]), (const void*)(&field.get(iX,iY)[0]), cellSize); 00464 iData += cellSize; 00465 } 00466 } 00467 } 00468 00469 template<typename T> 00470 void NTensorFieldDataTransfer2D<T>::receive ( 00471 Box2D domain, std::vector<char> const& buffer, modif::ModifT kind ) 00472 { 00473 PLB_PRECONDITION( contained(domain, field.getBoundingBox()) ); 00474 PLB_PRECONDITION( (pluint) domain.nCells()*staticCellSize() == buffer.size() ); 00475 plint cellSize = staticCellSize(); 00476 00477 plint iData=0; 00478 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00479 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00480 memcpy((void*)(&field.get(iX,iY)[0]), (const void*)(&buffer[iData]), cellSize); 00481 iData += cellSize; 00482 } 00483 } 00484 } 00485 00486 template<typename T> 00487 void NTensorFieldDataTransfer2D<T>::attribute ( 00488 Box2D toDomain, plint deltaX, plint deltaY, 00489 AtomicBlock2D const& from, modif::ModifT kind ) 00490 { 00491 PLB_PRECONDITION (typeid(from) == typeid(NTensorField2D<T> const&)); 00492 PLB_PRECONDITION( contained(toDomain, field.getBoundingBox()) ); 00493 NTensorField2D<T> const& fromField = (NTensorField2D<T> const&) from; 00494 for (plint iX=toDomain.x0; iX<=toDomain.x1; ++iX) { 00495 for (plint iY=toDomain.y0; iY<=toDomain.y1; ++iY) { 00496 for (int iDim=0; iDim<field.getNdim(); ++iDim) { 00497 field.get(iX,iY)[iDim] = fromField.get(iX+deltaX,iY+deltaY)[iDim]; 00498 } 00499 } 00500 } 00501 } 00502 00503 } // namespace plb 00504 00505 #endif // DATA_FIELD_2D_HH