$treeview $search $mathjax
|
Palabos
Version 1.1
$projectbrief
|
$projectbrief
|
$searchbox |
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 #ifndef GRID_CONVERSION_3D_HH 00026 #define GRID_CONVERSION_3D_HH 00027 00028 #include <algorithm> 00029 #include "multiGrid/gridConversion3D.h" 00030 #include "finiteDifference/interpolations3D.h" 00031 00032 namespace plb { 00033 00034 /* ******************* ScalarCopyFineToCoarseZerothOrder3D ******************* */ 00035 00036 template<typename T> 00037 ScalarCopyFineToCoarseZerothOrder3D<T>::ScalarCopyFineToCoarseZerothOrder3D 00038 (plint dimDx_, plint dimDt_, plint dxScale_, plint dtScale_) 00039 : dimDx(dimDx_), dimDt(dimDt_), dxScale(dxScale_), dtScale(dtScale_) 00040 { 00041 // X scale must be positive because the conversion goes from fine to coarse. 00042 PLB_ASSERT( dxScale >= 1 ); 00043 } 00044 00045 template<typename T> 00046 ScalarCopyFineToCoarseZerothOrder3D<T>::ScalarCopyFineToCoarseZerothOrder3D( 00047 ScalarCopyFineToCoarseZerothOrder3D<T> const& rhs) 00048 : dimDx(rhs.dimDx), dimDt(rhs.dimDt), 00049 dxScale(rhs.dxScale), dtScale(rhs.dtScale) 00050 { } 00051 00052 template<typename T> 00053 ScalarCopyFineToCoarseZerothOrder3D<T>& 00054 ScalarCopyFineToCoarseZerothOrder3D<T>::operator= ( 00055 ScalarCopyFineToCoarseZerothOrder3D<T> const& rhs ) 00056 { 00057 dimDx = rhs.dimDx; 00058 dimDt = rhs.dimDt; 00059 dxScale = rhs.dxScale; 00060 dtScale = rhs.dtScale; 00061 } 00062 00063 template<typename T> 00064 void ScalarCopyFineToCoarseZerothOrder3D<T>::process ( 00065 Box3D fineDomain, ScalarField3D<T>& fineField, ScalarField3D<T>& coarseField ) 00066 { 00067 Dot3D posFine = fineField.getLocation(); 00068 Dot3D posCoarse = coarseField.getLocation(); 00069 00070 plint stretch = util::twoToThePower(dxScale); 00071 Box3D coarseDomain ( 00072 fineDomain.shift(posFine.x,posFine.y, posFine.z). // Convert to absolute fine coordinates. 00073 divideAndFitSmaller(stretch). // Rescale, but don't exceed original domain. 00074 shift(-posCoarse.x,-posCoarse.y,-posCoarse.z) ); // Convert to relative coarse coordinates. 00075 PLB_ASSERT( contained(coarseDomain, coarseField.getBoundingBox()) ); 00076 00077 T scaleFactor = scaleFromReference(dxScale, dimDx, dtScale, dimDt); 00078 00079 plint fineX = (coarseDomain.x0+posCoarse.x)*stretch - posFine.x; 00080 for (plint coarseX=coarseDomain.x0; coarseX<=coarseDomain.x1; ++coarseX, fineX+=stretch) { 00081 plint fineY = (coarseDomain.y0+posCoarse.y)*stretch - posFine.y; 00082 for (plint coarseY=coarseDomain.y0; coarseY<=coarseDomain.y1; ++coarseY, fineY+=stretch) { 00083 plint fineZ = (coarseDomain.z0+posCoarse.z)*stretch - posFine.z; 00084 for (plint coarseZ=coarseDomain.z0; coarseZ<=coarseDomain.z1; ++coarseZ, fineZ+=stretch) { 00085 coarseField.get(coarseX,coarseY,coarseZ) = 00086 fineField.get(fineX,fineY,fineZ)*scaleFactor; 00087 } 00088 } 00089 } 00090 } 00091 00092 template<typename T> 00093 ScalarCopyFineToCoarseZerothOrder3D<T>* ScalarCopyFineToCoarseZerothOrder3D<T>::clone() const{ 00094 return new ScalarCopyFineToCoarseZerothOrder3D<T>(*this); 00095 } 00096 00097 00098 /* ******************* TensorCopyFineToCoarseZerothOrder3D ******************* */ 00099 00100 template<typename T, int nDim> 00101 TensorCopyFineToCoarseZerothOrder3D<T,nDim>::TensorCopyFineToCoarseZerothOrder3D 00102 (plint dimDx_, plint dimDt_, plint dxScale_, plint dtScale_) 00103 : dimDx(dimDx_), dimDt(dimDt_), dxScale(dxScale_), dtScale(dtScale_) 00104 { 00105 // X scale must be positive because the conversion goes from fine to coarse. 00106 PLB_ASSERT( dxScale >= 1 ); 00107 } 00108 00109 template<typename T, int nDim> 00110 TensorCopyFineToCoarseZerothOrder3D<T,nDim>::TensorCopyFineToCoarseZerothOrder3D( 00111 TensorCopyFineToCoarseZerothOrder3D<T,nDim> const& rhs) 00112 : dimDx(rhs.dimDx), dimDt(rhs.dimDt), 00113 dxScale(rhs.dxScale), dtScale(rhs.dtScale) 00114 { } 00115 00116 template<typename T, int nDim> 00117 TensorCopyFineToCoarseZerothOrder3D<T,nDim>& 00118 TensorCopyFineToCoarseZerothOrder3D<T,nDim>::operator= ( 00119 TensorCopyFineToCoarseZerothOrder3D<T,nDim> const& rhs ) 00120 { 00121 dimDx = rhs.dimDx; 00122 dimDt = rhs.dimDt; 00123 dxScale = rhs.dxScale; 00124 dtScale = rhs.dtScale; 00125 } 00126 00127 template<typename T, int nDim> 00128 void TensorCopyFineToCoarseZerothOrder3D<T,nDim>::process ( 00129 Box3D fineDomain, TensorField3D<T,nDim>& fineField, TensorField3D<T,nDim>& coarseField ) 00130 { 00131 Dot3D posFine = fineField.getLocation(); 00132 Dot3D posCoarse = coarseField.getLocation(); 00133 00134 plint stretch = util::twoToThePower(dxScale); 00135 Box3D coarseDomain ( 00136 fineDomain.shift(posFine.x,posFine.y, posFine.z). // Convert to absolute fine coordinates. 00137 divideAndFitSmaller(stretch). // Rescale, but don't exceed original domain. 00138 shift(-posCoarse.x,-posCoarse.y,-posCoarse.z) ); // Convert to relative coarse coordinates. 00139 PLB_ASSERT( contained(coarseDomain, coarseField.getBoundingBox()) ); 00140 00141 T scaleFactor = scaleFromReference(dxScale, dimDx, dtScale, dimDt); 00142 00143 plint fineX = (coarseDomain.x0+posCoarse.x)*stretch - posFine.x; 00144 for (plint coarseX=coarseDomain.x0; coarseX<=coarseDomain.x1; ++coarseX, fineX+=stretch) { 00145 plint fineY = (coarseDomain.y0+posCoarse.y)*stretch - posFine.y; 00146 for (plint coarseY=coarseDomain.y0; coarseY<=coarseDomain.y1; ++coarseY, fineY+=stretch) { 00147 plint fineZ = (coarseDomain.z0+posCoarse.z)*stretch - posFine.z; 00148 for (plint coarseZ=coarseDomain.z0; coarseZ<=coarseDomain.z1; ++coarseZ, fineZ+=stretch) { 00149 coarseField.get(coarseX,coarseY,coarseZ) = 00150 fineField.get(fineX,fineY,fineZ)*scaleFactor; 00151 } 00152 } 00153 } 00154 } 00155 00156 template<typename T, int nDim> 00157 TensorCopyFineToCoarseZerothOrder3D<T,nDim>* TensorCopyFineToCoarseZerothOrder3D<T,nDim>::clone() const{ 00158 return new TensorCopyFineToCoarseZerothOrder3D<T,nDim>(*this); 00159 } 00160 00161 00162 /* ******************* LatticeCopyFineToCoarseZerothOrder3D ******************* */ 00163 00164 template<typename T, template<typename U> class Descriptor> 00165 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>::LatticeCopyFineToCoarseZerothOrder3D 00166 (plint dxScale_, plint dtScale_) 00167 : dxScale(dxScale_), dtScale(dtScale_) 00168 { 00169 // X scale must be positive because the conversion goes from fine to coarse. 00170 PLB_ASSERT( dxScale >= 1 ); 00171 } 00172 00173 template<typename T, template<typename U> class Descriptor> 00174 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>::LatticeCopyFineToCoarseZerothOrder3D( 00175 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor> const& rhs) 00176 : dxScale(rhs.dxScale), dtScale(rhs.dtScale) 00177 { } 00178 00179 template<typename T, template<typename U> class Descriptor> 00180 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>& 00181 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>::operator= ( 00182 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor> const& rhs ) 00183 { 00184 dxScale = rhs.dxScale; 00185 dtScale = rhs.dtScale; 00186 } 00187 00188 template<typename T, template<typename U> class Descriptor> 00189 void LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>::process ( 00190 Box3D fineDomain, 00191 BlockLattice3D<T,Descriptor>& fineLattice, BlockLattice3D<T,Descriptor>& coarseLattice ) 00192 { 00193 static const int velDimDx = 1; 00194 static const int velDimDt = -1; 00195 static const int presDimDx = 2; 00196 static const int presDimDt = -2; 00197 static const int viscDimDx = 2; 00198 static const int viscDimDt = -1; 00199 static const int fNeqDimDx = 0; 00200 static const int fNeqDimDt = -1; 00201 T velScale = scaleFromReference(dxScale, velDimDx, dtScale, velDimDt); 00202 T presScale = scaleFromReference(dxScale, presDimDx, dtScale, presDimDt); 00203 T viscScale = scaleFromReference(dxScale, viscDimDx, dtScale, viscDimDt); 00204 T fNeqScale = scaleFromReference(dxScale, fNeqDimDx, dtScale, fNeqDimDt); 00205 00206 Dot3D posFine = fineLattice.getLocation(); 00207 Dot3D posCoarse = coarseLattice.getLocation(); 00208 00209 plint stretch = util::twoToThePower(dxScale); 00210 Box3D coarseDomain ( 00211 fineDomain.shift(posFine.x,posFine.y, posFine.z). // Convert to absolute fine coordinates. 00212 divideAndFitSmaller(stretch). // Rescale, but don't exceed original domain. 00213 shift(-posCoarse.x,-posCoarse.y,-posCoarse.z) ); // Convert to relative coarse coordinates. 00214 PLB_ASSERT( contained(coarseDomain, coarseLattice.getBoundingBox()) ); 00215 00216 plint fineX = (coarseDomain.x0+posCoarse.x)*stretch - posFine.x; 00217 for (plint coarseX=coarseDomain.x0; coarseX<=coarseDomain.x1; ++coarseX, fineX+=stretch) { 00218 plint fineY = (coarseDomain.y0+posCoarse.y)*stretch - posFine.y; 00219 for (plint coarseY=coarseDomain.y0; coarseY<=coarseDomain.y1; ++coarseY, fineY+=stretch) { 00220 plint fineZ = (coarseDomain.z0+posCoarse.z)*stretch - posFine.z; 00221 for (plint coarseZ=coarseDomain.z0; coarseZ<=coarseDomain.z1; ++coarseZ, fineZ+=stretch) { 00222 // Fine --> Coarse 00223 Cell<T,Descriptor> const& fineCell = fineLattice.get(fineX,fineY,fineZ); 00224 Cell<T,Descriptor>& coarseCell = coarseLattice.get(coarseX,coarseY,coarseZ); 00225 T fineOmega = fineCell.getDynamics().getOmega(); 00226 T fine_nu_cs2 = 1./fineOmega - 0.5; 00227 T coarse_nu_cs2 = viscScale * fine_nu_cs2; 00228 T coarseOmega = 1. / (coarse_nu_cs2+0.5); 00229 coarseCell.getDynamics().setOmega(coarseOmega); 00230 00231 T localFneqScale = fNeqScale * fineOmega / coarseOmega; 00232 plint numComponents = 1+Descriptor<T>::d+Descriptor<T>::q+Descriptor<T>::ExternalField::numScalars; 00233 // TODO: For now external scalars are set to zero during conversion. They should be 00234 // rescaled properly. 00235 std::vector<T> components(numComponents); 00236 std::fill(components.begin(), components.end(), 0.); 00237 plint order = 0; 00238 fineCell.getDynamics().decompose(fineCell, components, order); 00239 T rhoFine = Descriptor<T>::fullRho(components[0]); 00240 if (!fineCell.getDynamics().velIsJ()) { 00241 for (plint iDim=0; iDim<Descriptor<T>::d; ++iDim) { 00242 components[1+iDim] /= rhoFine; 00243 } 00244 } 00245 // 1. Density. 00246 T p_cs2 = components[0]-(1-Descriptor<T>::SkordosFactor()); 00247 components[0] = (1-Descriptor<T>::SkordosFactor()) + p_cs2*presScale; 00248 // 2. Velocity. 00249 for (plint iDim=0; iDim<Descriptor<T>::d; ++iDim) { 00250 components[1+iDim] *= velScale; 00251 } 00252 // 3. Off-equilibrium populations. 00253 for (plint iPop=0; iPop<Descriptor<T>::q; ++iPop) { 00254 components[1+Descriptor<T>::d+iPop] *= localFneqScale; 00255 } 00256 T rhoCoarse = Descriptor<T>::fullRho(components[0]); 00257 if (!coarseCell.getDynamics().velIsJ()) { 00258 for (plint iDim=0; iDim<Descriptor<T>::d; ++iDim) { 00259 components[1+iDim] *= rhoCoarse; 00260 } 00261 } 00262 //coarseCell.getDynamics().recompose(coarseCell, components, order); 00263 // For recomposition, get the dynamics from the fine cell, because the fine/coarse dynamics 00264 // may not have the same number of variables in the decomposed vector. 00265 fineCell.getDynamics().recompose(coarseCell, components, order); 00266 } 00267 } 00268 } 00269 } 00270 00271 template<typename T, template<typename U> class Descriptor> 00272 LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>* LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>::clone() const{ 00273 return new LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>(*this); 00274 } 00275 00276 00277 /* ******************* CopyRescaleParticles3D ******************* */ 00278 00279 template<typename T, template<typename U> class Descriptor> 00280 CopyRescaleParticles3D<T,Descriptor>::CopyRescaleParticles3D(plint dxScale_, plint dtScale_) 00281 : dxScale(dxScale_), dtScale(dtScale_) 00282 { } 00283 00284 template<typename T, template<typename U> class Descriptor> 00285 void CopyRescaleParticles3D<T,Descriptor>::processGenericBlocks ( 00286 Box3D domain1, std::vector<AtomicBlock3D*> blocks ) 00287 { 00288 PLB_PRECONDITION( blocks.size()==2 ); 00289 ParticleField3D<T,Descriptor>& field1 = 00290 *dynamic_cast<ParticleField3D<T,Descriptor>*>(blocks[0]); 00291 ParticleField3D<T,Descriptor>& field2 = 00292 *dynamic_cast<ParticleField3D<T,Descriptor>*>(blocks[1]); 00293 00294 Box3D domain2(field2.getBoundingBox()); 00295 std::vector<Particle3D<T,Descriptor>*> particles; 00296 field1.findParticles(domain1, particles); 00297 for (pluint iParticle=0; iParticle<particles.size(); ++iParticle) { 00298 Particle3D<T,Descriptor>* newparticle = particles[iParticle]->clone(); 00299 newparticle->rescale(dxScale, dtScale); 00300 field2.addParticle(domain2, newparticle); 00301 } 00302 } 00303 00304 00305 template<typename T, template<typename U> class Descriptor> 00306 CopyRescaleParticles3D<T,Descriptor>* CopyRescaleParticles3D<T,Descriptor>::clone() const{ 00307 return new CopyRescaleParticles3D<T,Descriptor>(*this); 00308 } 00309 00310 00311 /* ******************* ScalarInterpolateCoarseToFine3D ******************* */ 00312 00313 template<typename T> 00314 ScalarInterpolateCoarseToFine3D<T>::ScalarInterpolateCoarseToFine3D 00315 (plint dimDx_, plint dimDt_, plint dxScale_, plint dtScale_) 00316 : dimDx(dimDx_), dimDt(dimDt_), dxScale(dxScale_), dtScale(dtScale_) 00317 { 00318 // X scale must be negative because the conversion goes from coarse to fine. 00319 PLB_ASSERT( dxScale <= -1 ); 00320 } 00321 00322 template<typename T> 00323 ScalarInterpolateCoarseToFine3D<T>::ScalarInterpolateCoarseToFine3D( 00324 ScalarInterpolateCoarseToFine3D<T> const& rhs) 00325 : dimDx(rhs.dimDx), dimDt(rhs.dimDt), 00326 dxScale(rhs.dxScale), dtScale(rhs.dtScale) 00327 { } 00328 00329 template<typename T> 00330 ScalarInterpolateCoarseToFine3D<T>& 00331 ScalarInterpolateCoarseToFine3D<T>::operator= ( 00332 ScalarInterpolateCoarseToFine3D<T> const& rhs ) 00333 { 00334 dimDx = rhs.dimDx; 00335 dimDt = rhs.dimDt; 00336 dxScale = rhs.dxScale; 00337 dtScale = rhs.dtScale; 00338 } 00339 00340 template<typename T> 00341 void ScalarInterpolateCoarseToFine3D<T>::process ( 00342 Box3D coarseDomain, 00343 ScalarField3D<T>& coarseField, ScalarField3D<T>& fineField ) 00344 { 00345 Dot3D posFine = fineField.getLocation(); 00346 Dot3D posCoarse = coarseField.getLocation(); 00347 00348 plint stretch = util::twoToThePower(-dxScale); 00349 T scaleFactor = scaleFromReference(dxScale, dimDx, dtScale, dimDt); 00350 00351 std::vector<Dot3D> cellPos; 00352 std::vector<T> weights; 00353 for (plint coarseX=coarseDomain.x0; coarseX<=coarseDomain.x1; ++coarseX) { 00354 plint fineX = (coarseX+posCoarse.x)*stretch - posFine.x; 00355 for (plint coarseY=coarseDomain.y0; coarseY<=coarseDomain.y1; ++coarseY) { 00356 plint fineY = (coarseY+posCoarse.y)*stretch - posFine.y; 00357 for (plint coarseZ=coarseDomain.z0; coarseZ<=coarseDomain.z1; ++coarseZ) { 00358 plint fineZ = (coarseZ+posCoarse.z)*stretch - posFine.z; 00359 for (plint iX=fineX-stretch/2+1; iX<=fineX+stretch/2; ++iX) { 00360 for (plint iY=fineY-stretch/2+1; iY<=fineY+stretch/2; ++iY) { 00361 for (plint iZ=fineZ-stretch/2+1; iZ<=fineZ+stretch/2; ++iZ) { 00362 if (contained(iX,iY,iZ, fineField.getBoundingBox())) { 00363 T coarseIx = (T)(iX + posFine.x)/(T)stretch; 00364 T coarseIy = (T)(iY + posFine.y)/(T)stretch; 00365 T coarseIz = (T)(iZ + posFine.z)/(T)stretch; 00366 linearInterpolationCoefficients<T>(coarseField, Array<T,3> ( 00367 coarseIx, coarseIy, coarseIz), cellPos, weights ); 00368 fineField.get(iX,iY,iZ) = 0.; 00369 for (plint i=0; i<8; ++i) { 00370 fineField.get(iX,iY,iZ) += 00371 weights[i] * coarseField.get(cellPos[i].x, cellPos[i].y, cellPos[i].z); 00372 } 00373 fineField.get(iX,iY,iZ) *= scaleFactor; 00374 } 00375 } } } 00376 } 00377 } 00378 } 00379 } 00380 00381 template<typename T> 00382 ScalarInterpolateCoarseToFine3D<T>* ScalarInterpolateCoarseToFine3D<T>::clone() const{ 00383 return new ScalarInterpolateCoarseToFine3D<T>(*this); 00384 } 00385 00386 00387 00388 /* ******************* TensorInterpolateCoarseToFine3D ******************* */ 00389 00390 template<typename T, int nDim> 00391 TensorInterpolateCoarseToFine3D<T,nDim>::TensorInterpolateCoarseToFine3D 00392 (plint dimDx_, plint dimDt_, plint dxScale_, plint dtScale_) 00393 : dimDx(dimDx_), dimDt(dimDt_), dxScale(dxScale_), dtScale(dtScale_) 00394 { 00395 // X scale must be negative because the conversion goes from coarse to fine. 00396 PLB_ASSERT( dxScale <= -1 ); 00397 } 00398 00399 template<typename T, int nDim> 00400 TensorInterpolateCoarseToFine3D<T,nDim>::TensorInterpolateCoarseToFine3D( 00401 TensorInterpolateCoarseToFine3D<T,nDim> const& rhs) 00402 : dimDx(rhs.dimDx), dimDt(rhs.dimDt), 00403 dxScale(rhs.dxScale), dtScale(rhs.dtScale) 00404 { } 00405 00406 template<typename T, int nDim> 00407 TensorInterpolateCoarseToFine3D<T,nDim>& 00408 TensorInterpolateCoarseToFine3D<T,nDim>::operator= ( 00409 TensorInterpolateCoarseToFine3D<T,nDim> const& rhs ) 00410 { 00411 dimDx = rhs.dimDx; 00412 dimDt = rhs.dimDt; 00413 dxScale = rhs.dxScale; 00414 dtScale = rhs.dtScale; 00415 } 00416 00417 template<typename T, int nDim> 00418 void TensorInterpolateCoarseToFine3D<T,nDim>::process ( 00419 Box3D coarseDomain, 00420 TensorField3D<T,nDim>& coarseField, TensorField3D<T,nDim>& fineField ) 00421 { 00422 Dot3D posFine = fineField.getLocation(); 00423 Dot3D posCoarse = coarseField.getLocation(); 00424 00425 plint stretch = util::twoToThePower(-dxScale); 00426 T scaleFactor = scaleFromReference(dxScale, dimDx, dtScale, dimDt); 00427 00428 std::vector<Dot3D> cellPos; 00429 std::vector<T> weights; 00430 for (plint coarseX=coarseDomain.x0; coarseX<=coarseDomain.x1; ++coarseX) { 00431 plint fineX = (coarseX+posCoarse.x)*stretch - posFine.x; 00432 for (plint coarseY=coarseDomain.y0; coarseY<=coarseDomain.y1; ++coarseY) { 00433 plint fineY = (coarseY+posCoarse.y)*stretch - posFine.y; 00434 for (plint coarseZ=coarseDomain.z0; coarseZ<=coarseDomain.z1; ++coarseZ) { 00435 plint fineZ = (coarseZ+posCoarse.z)*stretch - posFine.z; 00436 for (plint iX=fineX-stretch/2+1; iX<=fineX+stretch/2; ++iX) { 00437 for (plint iY=fineY-stretch/2+1; iY<=fineY+stretch/2; ++iY) { 00438 for (plint iZ=fineZ-stretch/2+1; iZ<=fineZ+stretch/2; ++iZ) { 00439 if (contained(iX,iY,iZ, fineField.getBoundingBox())) { 00440 T coarseIx = (T)(iX + posFine.x)/(T)stretch; 00441 T coarseIy = (T)(iY + posFine.y)/(T)stretch; 00442 T coarseIz = (T)(iZ + posFine.z)/(T)stretch; 00443 linearInterpolationCoefficients(coarseField, Array<T,3> ( 00444 coarseIx, coarseIy, coarseIz), cellPos, weights ); 00445 fineField.get(iX,iY,iZ).resetToZero(); 00446 for (plint i=0; i<8; ++i) { 00447 fineField.get(iX,iY,iZ) += 00448 weights[i] * coarseField.get(cellPos[i].x, cellPos[i].y, cellPos[i].z); 00449 } 00450 fineField.get(iX,iY,iZ) *= scaleFactor; 00451 } 00452 } } } 00453 } 00454 } 00455 } 00456 } 00457 00458 template<typename T, int nDim> 00459 TensorInterpolateCoarseToFine3D<T,nDim>* TensorInterpolateCoarseToFine3D<T,nDim>::clone() const{ 00460 return new TensorInterpolateCoarseToFine3D<T,nDim>(*this); 00461 } 00462 00463 00464 00465 /* ******************* LatticeInterpolateCoarseToFine3D ******************* */ 00466 00467 template<typename T, template<typename U> class Descriptor> 00468 LatticeInterpolateCoarseToFine3D<T,Descriptor>::LatticeInterpolateCoarseToFine3D 00469 (plint dxScale_, plint dtScale_) 00470 : dxScale(dxScale_), dtScale(dtScale_) 00471 { 00472 // X scale must be negative because the conversion goes from coarse to fine. 00473 PLB_ASSERT( dxScale <= -1 ); 00474 } 00475 00476 template<typename T, template<typename U> class Descriptor> 00477 LatticeInterpolateCoarseToFine3D<T,Descriptor>::LatticeInterpolateCoarseToFine3D( 00478 LatticeInterpolateCoarseToFine3D<T,Descriptor> const& rhs) 00479 : dxScale(rhs.dxScale), dtScale(rhs.dtScale) 00480 { } 00481 00482 template<typename T, template<typename U> class Descriptor> 00483 LatticeInterpolateCoarseToFine3D<T,Descriptor>& 00484 LatticeInterpolateCoarseToFine3D<T,Descriptor>::operator= ( 00485 LatticeInterpolateCoarseToFine3D<T,Descriptor> const& rhs ) 00486 { 00487 dxScale = rhs.dxScale; 00488 dtScale = rhs.dtScale; 00489 } 00490 00491 template<typename T, template<typename U> class Descriptor> 00492 void LatticeInterpolateCoarseToFine3D<T,Descriptor>::process ( 00493 Box3D coarseDomain, 00494 BlockLattice3D<T,Descriptor>& coarseLattice, BlockLattice3D<T,Descriptor>& fineLattice ) 00495 { 00496 static const int velDimDx = 1; 00497 static const int velDimDt = -1; 00498 static const int presDimDx = 2; 00499 static const int presDimDt = -2; 00500 static const int viscDimDx = 2; 00501 static const int viscDimDt = -1; 00502 static const int fNeqDimDx = 0; 00503 static const int fNeqDimDt = -1; 00504 T velScale = scaleFromReference(dxScale, velDimDx, dtScale, velDimDt); 00505 T presScale = scaleFromReference(dxScale, presDimDx, dtScale, presDimDt); 00506 T viscScale = scaleFromReference(dxScale, viscDimDx, dtScale, viscDimDt); 00507 T fNeqScale = scaleFromReference(dxScale, fNeqDimDx, dtScale, fNeqDimDt); 00508 00509 Dot3D posFine = fineLattice.getLocation(); 00510 Dot3D posCoarse = coarseLattice.getLocation(); 00511 00512 plint stretch = util::twoToThePower(-dxScale); 00513 00514 std::vector<Dot3D> cellPos; 00515 std::vector<T> weights; 00516 for (plint coarseX=coarseDomain.x0; coarseX<=coarseDomain.x1; ++coarseX) { 00517 plint fineX = (coarseX+posCoarse.x)*stretch - posFine.x; 00518 for (plint coarseY=coarseDomain.y0; coarseY<=coarseDomain.y1; ++coarseY) { 00519 plint fineY = (coarseY+posCoarse.y)*stretch - posFine.y; 00520 for (plint coarseZ=coarseDomain.z0; coarseZ<=coarseDomain.z1; ++coarseZ) { 00521 plint fineZ = (coarseZ+posCoarse.z)*stretch - posFine.z; 00522 for (plint iX=fineX-stretch/2+1; iX<=fineX+stretch/2; ++iX) { 00523 for (plint iY=fineY-stretch/2+1; iY<=fineY+stretch/2; ++iY) { 00524 for (plint iZ=fineZ-stretch/2+1; iZ<=fineZ+stretch/2; ++iZ) { 00525 if (contained(iX,iY,iZ, fineLattice.getBoundingBox())) { 00526 T coarseIx = (T)(iX + posFine.x)/(T)stretch; 00527 T coarseIy = (T)(iY + posFine.y)/(T)stretch; 00528 T coarseIz = (T)(iZ + posFine.z)/(T)stretch; 00529 linearInterpolationCoefficients(coarseLattice, Array<T,3> ( 00530 coarseIx, coarseIy, coarseIz), cellPos, weights ); 00531 plint order = 0; 00532 plint numComponents = 1+Descriptor<T>::d+Descriptor<T>::q+Descriptor<T>::ExternalField::numScalars; 00533 // TODO: For now external scalars are set to zero during conversion. They should be 00534 // rescaled properly. 00535 std::vector<T> components(numComponents), oldComponents(numComponents); 00536 std::fill(components.begin(), components.end(), 0.); 00537 T coarse_nu_cs2 = 0.; 00538 components[0] = 1-Descriptor<T>::SkordosFactor(); // Density offset. 00539 for (plint i=0; i<8; ++i) { 00540 Cell<T,Descriptor> const& coarseCell = 00541 coarseLattice.get(cellPos[i].x, cellPos[i].y, cellPos[i].z); 00542 T coarseOmega = coarseCell.getDynamics().getOmega(); 00543 T coarse_nu_cs2 = 1./coarseOmega - 0.5; 00544 coarse_nu_cs2 += weights[i]*coarse_nu_cs2; 00545 coarseCell.getDynamics().decompose(coarseCell, oldComponents, order); 00546 T coarseRho = Descriptor<T>::fullRho(oldComponents[0]); 00547 // 1. Density 00548 T pres_cs2 = oldComponents[0]-(1-Descriptor<T>::SkordosFactor()); 00549 components[0] += weights[i]*pres_cs2*presScale; 00550 // 2. Velocity. 00551 Array<T,3> vel; 00552 coarseCell.computeVelocity(vel); 00553 T multFactor = weights[i]*velScale; 00554 if (!coarseCell.getDynamics().velIsJ()) { 00555 multFactor /= coarseRho; 00556 } 00557 for (plint iDim=0; iDim<Descriptor<T>::d; ++iDim) { 00558 components[1+iDim] += multFactor*oldComponents[1+iDim]; 00559 } 00560 // 3. Off-equilibrium populations. 00561 for (plint iPop=0; iPop<Descriptor<T>::q; ++iPop) { 00562 components[1+Descriptor<T>::d+iPop] += weights[i]*fNeqScale* 00563 oldComponents[1+Descriptor<T>::d+iPop]; 00564 } 00565 } 00566 Cell<T,Descriptor>& fineCell = fineLattice.get(iX,iY,iZ); 00567 T fineRho = Descriptor<T>::fullRho(components[0]); 00568 if (!fineCell.getDynamics().velIsJ()) { 00569 for (plint iDim=0; iDim<Descriptor<T>::d; ++iDim) { 00570 components[1+iDim] *= fineRho; 00571 } 00572 } 00573 T fine_nu_cs2 = coarse_nu_cs2*viscScale; 00574 T coarseOmega = 1. / (coarse_nu_cs2+0.5); 00575 T fineOmega = 1. / (fine_nu_cs2+0.5); 00576 T omegaRatio = coarseOmega / fineOmega; 00577 for (plint iPop=0; iPop<Descriptor<T>::q; ++iPop) { 00578 components[1+Descriptor<T>::d+iPop] *= omegaRatio; 00579 } 00580 fineCell.getDynamics().setOmega(fineOmega); 00581 fineCell.getDynamics().recompose(fineCell, components, order); 00582 } 00583 } } } 00584 } 00585 } 00586 } 00587 } 00588 00589 template<typename T, template<typename U> class Descriptor> 00590 LatticeInterpolateCoarseToFine3D<T,Descriptor>* LatticeInterpolateCoarseToFine3D<T,Descriptor>::clone() const{ 00591 return new LatticeInterpolateCoarseToFine3D<T,Descriptor>(*this); 00592 } 00593 00594 00595 /* ******************* Free functions ******************* */ 00596 00597 inline Box3D scaleBox(Box3D box, plint nLevel) 00598 { 00599 if (nLevel>0) { 00600 return box.multiply(util::twoToThePower(nLevel)); 00601 } 00602 else if (nLevel<0) { 00603 // If the fine-grid box does not fit with the coarse-grid box, 00604 // let's shrink the coarse-grid box by one fine cell. This 00605 // makes sure we'll never exceed the fine-grid box 00606 return box.divideAndFitSmaller(util::twoToThePower(-nLevel)); 00607 } 00608 else { 00609 return box; 00610 } 00611 } 00612 00613 inline MultiBlockManagement3D scaleMultiBlockManagement ( 00614 MultiBlockManagement3D const& multiBlockManagement, plint nLevel ) 00615 { 00616 SparseBlockStructure3D const& sparseBlock = multiBlockManagement.getSparseBlockStructure(); 00617 00618 Box3D rescaledBoundingBox = scaleBox(sparseBlock.getBoundingBox(), nLevel); 00619 SparseBlockStructure3D scaledSparseBlock(rescaledBoundingBox); 00620 plint stretch = util::twoToThePower(nLevel); 00621 00622 std::map<plint,Box3D>::const_iterator it = sparseBlock.getBulks().begin(); 00623 for (; it != sparseBlock.getBulks().end(); ++it) { 00624 Box3D scaledBulk = scaleBox(it->second, nLevel); 00625 if (stretch>1) { 00626 scaledBulk.x0 -= stretch/2-1; 00627 scaledBulk.y0 -= stretch/2-1; 00628 scaledBulk.z0 -= stretch/2-1; 00629 scaledBulk.x1 += stretch/2; 00630 scaledBulk.y1 += stretch/2; 00631 scaledBulk.z1 += stretch/2; 00632 } 00633 Box3D scaledUniqueBulk = scaledBulk; //TODO: compute unique bulk properly. 00634 plint blockId = it->first; 00635 scaledSparseBlock.addBlock(scaledBulk, scaledUniqueBulk, blockId); 00636 } 00637 return MultiBlockManagement3D ( 00638 scaledSparseBlock, 00639 multiBlockManagement.getThreadAttribution().clone(), 00640 multiBlockManagement.getEnvelopeWidth(), 00641 multiBlockManagement.getRefinementLevel()+nLevel ); 00642 } 00643 00644 00645 template<typename T> 00646 std::auto_ptr<MultiScalarField3D<T> > coarsen ( 00647 MultiScalarField3D<T>& fineField, 00648 plint dimDx, plint dimDt, plint dxScale, plint dtScale ) 00649 { 00650 PLB_PRECONDITION( dxScale>=1 ); 00651 // Relative level is negative when going from fine to coarse. 00652 plint relativeLevel = -dxScale; 00653 MultiBlockManagement3D management = scaleMultiBlockManagement(fineField.getMultiBlockManagement(),relativeLevel); 00654 MultiScalarField3D<T>* result = new MultiScalarField3D<T> ( 00655 management, 00656 defaultMultiBlockPolicy3D().getBlockCommunicator(), 00657 defaultMultiBlockPolicy3D().getCombinedStatistics(), 00658 defaultMultiBlockPolicy3D().getMultiScalarAccess<T>() ); 00659 applyProcessingFunctional ( 00660 new ScalarCopyFineToCoarseZerothOrder3D<T>(dimDx,dimDt,dxScale,dtScale), 00661 fineField.getBoundingBox(), fineField, *result ); 00662 00663 return std::auto_ptr<MultiScalarField3D<T> >(result); 00664 } 00665 00666 template<typename T, int nDim> 00667 std::auto_ptr<MultiTensorField3D<T,nDim> > coarsen ( 00668 MultiTensorField3D<T,nDim>& fineField, 00669 plint dimDx, plint dimDt, plint dxScale, plint dtScale ) 00670 { 00671 PLB_PRECONDITION( dxScale>=1 ); 00672 // Relative level is negative when going from fine to coarse. 00673 plint relativeLevel = -dxScale; 00674 MultiBlockManagement3D management = scaleMultiBlockManagement(fineField.getMultiBlockManagement(),relativeLevel); 00675 MultiTensorField3D<T,nDim>* result = new MultiTensorField3D<T,nDim> ( 00676 management, 00677 defaultMultiBlockPolicy3D().getBlockCommunicator(), 00678 defaultMultiBlockPolicy3D().getCombinedStatistics(), 00679 defaultMultiBlockPolicy3D().getMultiTensorAccess<T,nDim>() ); 00680 applyProcessingFunctional ( 00681 new TensorCopyFineToCoarseZerothOrder3D<T,nDim>(dimDx,dimDt,dxScale,dtScale), 00682 fineField.getBoundingBox(), fineField, *result ); 00683 00684 return std::auto_ptr<MultiTensorField3D<T,nDim> >(result); 00685 } 00686 00687 template <typename T> 00688 std::auto_ptr<MultiScalarField3D<T> > refine ( 00689 MultiScalarField3D<T>& coarseField, 00690 plint dimDx, plint dimDt, plint dxScale, plint dtScale ) 00691 { 00692 PLB_PRECONDITION( dxScale<=-1 ); 00693 // Relative level is positive when going from coarse to fine. 00694 plint relativeLevel = -dxScale; 00695 MultiBlockManagement3D management 00696 = scaleMultiBlockManagement(coarseField.getMultiBlockManagement(),relativeLevel); 00697 MultiScalarField3D<T>* result = new MultiScalarField3D<T> ( 00698 management, 00699 defaultMultiBlockPolicy3D().getBlockCommunicator(), 00700 defaultMultiBlockPolicy3D().getCombinedStatistics(), 00701 defaultMultiBlockPolicy3D().getMultiScalarAccess<T>() ); 00702 applyProcessingFunctional ( 00703 new ScalarInterpolateCoarseToFine3D<T>(dimDx,dimDt,dxScale,dtScale), 00704 coarseField.getBoundingBox(), coarseField, *result ); 00705 00706 return std::auto_ptr<MultiScalarField3D<T> >(result); 00707 } 00708 00709 template <typename T, int nDim> 00710 std::auto_ptr<MultiTensorField3D<T,nDim> > refine ( 00711 MultiTensorField3D<T,nDim>& coarseField, 00712 plint dimDx, plint dimDt, plint dxScale, plint dtScale ) 00713 { 00714 PLB_PRECONDITION( dxScale<=-1 ); 00715 // Relative level is positive when going from coarse to fine. 00716 plint relativeLevel = -dxScale; 00717 MultiBlockManagement3D management 00718 = scaleMultiBlockManagement(coarseField.getMultiBlockManagement(),relativeLevel); 00719 MultiTensorField3D<T,nDim>* result = new MultiTensorField3D<T,nDim> ( 00720 management, 00721 defaultMultiBlockPolicy3D().getBlockCommunicator(), 00722 defaultMultiBlockPolicy3D().getCombinedStatistics(), 00723 defaultMultiBlockPolicy3D().getMultiTensorAccess<T,nDim>() ); 00724 applyProcessingFunctional ( 00725 new TensorInterpolateCoarseToFine3D<T,nDim>(dimDx,dimDt,dxScale,dtScale), 00726 coarseField.getBoundingBox(), coarseField, *result ); 00727 00728 return std::auto_ptr<MultiTensorField3D<T,nDim> >(result); 00729 } 00730 00731 template<typename T, template<typename U> class Descriptor> 00732 std::auto_ptr<MultiBlockLattice3D<T,Descriptor> > coarsen ( 00733 MultiBlockLattice3D<T,Descriptor>& fineLattice, 00734 plint dxScale, plint dtScale, Dynamics<T,Descriptor>* backgroundDynamics ) 00735 { 00736 PLB_PRECONDITION( dxScale>=1 ); 00737 // Relative level is negative when going from fine to coarse. 00738 plint relativeLevel = -dxScale; 00739 MultiBlockManagement3D management = 00740 scaleMultiBlockManagement(fineLattice.getMultiBlockManagement(),relativeLevel); 00741 MultiBlockLattice3D<T,Descriptor>* result = new MultiBlockLattice3D<T,Descriptor> ( 00742 management, 00743 defaultMultiBlockPolicy3D().getBlockCommunicator(), 00744 defaultMultiBlockPolicy3D().getCombinedStatistics(), 00745 defaultMultiBlockPolicy3D().getMultiCellAccess<T,Descriptor>(), 00746 backgroundDynamics->clone() ); 00747 defineDynamics(*result, result->getBoundingBox(), backgroundDynamics); 00748 applyProcessingFunctional ( 00749 new LatticeCopyFineToCoarseZerothOrder3D<T,Descriptor>(dxScale,dtScale), 00750 fineLattice.getBoundingBox(), fineLattice, *result ); 00751 00752 return std::auto_ptr<MultiBlockLattice3D<T,Descriptor> >(result); 00753 } 00754 00755 template<typename T, template<typename U> class Descriptor> 00756 std::auto_ptr<MultiBlockLattice3D<T,Descriptor> > refine ( 00757 MultiBlockLattice3D<T,Descriptor>& coarseLattice, 00758 plint dxScale, plint dtScale, Dynamics<T,Descriptor>* backgroundDynamics ) 00759 { 00760 PLB_PRECONDITION( dxScale<=-1 ); 00761 // Relative level is positive when going from coarse to fine. 00762 plint relativeLevel = -dxScale; 00763 MultiBlockManagement3D management 00764 = scaleMultiBlockManagement(coarseLattice.getMultiBlockManagement(),relativeLevel); 00765 MultiBlockLattice3D<T,Descriptor>* result = new MultiBlockLattice3D<T,Descriptor> ( 00766 management, 00767 defaultMultiBlockPolicy3D().getBlockCommunicator(), 00768 defaultMultiBlockPolicy3D().getCombinedStatistics(), 00769 defaultMultiBlockPolicy3D().getMultiCellAccess<T,Descriptor>(), 00770 backgroundDynamics->clone() ); 00771 defineDynamics(*result, result->getBoundingBox(), backgroundDynamics); 00772 applyProcessingFunctional ( 00773 new LatticeInterpolateCoarseToFine3D<T,Descriptor>(dxScale,dtScale), 00774 coarseLattice.getBoundingBox(), coarseLattice, *result ); 00775 00776 return std::auto_ptr<MultiBlockLattice3D<T,Descriptor> >(result); 00777 } 00778 00779 00780 template<typename T, template<typename U> class Descriptor> 00781 std::auto_ptr<MultiParticleField3D<DenseParticleField3D<T,Descriptor> > > refine ( 00782 MultiParticleField3D<DenseParticleField3D<T,Descriptor> >& coarseField, 00783 plint dxScale, plint dtScale ) 00784 { 00785 PLB_PRECONDITION( dxScale<=-1 ); 00786 // Relative level is positive when going from coarse to fine. 00787 plint relativeLevel = -dxScale; 00788 MultiBlockManagement3D management 00789 = scaleMultiBlockManagement(coarseField.getMultiBlockManagement(),relativeLevel); 00790 MultiParticleField3D<DenseParticleField3D<T,Descriptor> >* result = 00791 new MultiParticleField3D<DenseParticleField3D<T,Descriptor> > ( 00792 management, 00793 defaultMultiBlockPolicy3D().getCombinedStatistics() ); 00794 std::vector<MultiBlock3D*> args; 00795 args.push_back(&coarseField); 00796 args.push_back(result); 00797 applyProcessingFunctional ( 00798 new CopyRescaleParticles3D<T,Descriptor>(dxScale,dtScale), 00799 coarseField.getBoundingBox(), args ); 00800 00801 return std::auto_ptr<MultiParticleField3D<DenseParticleField3D<T,Descriptor> > >(result); 00802 } 00803 00804 template<typename T, template<typename U> class Descriptor> 00805 std::auto_ptr<MultiParticleField3D<DenseParticleField3D<T,Descriptor> > > coarsen ( 00806 MultiParticleField3D<DenseParticleField3D<T,Descriptor> >& fineField, 00807 plint dxScale, plint dtScale ) 00808 { 00809 PLB_PRECONDITION( dxScale>=1 ); 00810 // Relative level is negative when going from fine to coarse. 00811 plint relativeLevel = -dxScale; 00812 MultiBlockManagement3D management = 00813 scaleMultiBlockManagement(fineField.getMultiBlockManagement(),relativeLevel); 00814 MultiParticleField3D<DenseParticleField3D<T,Descriptor> >* result = 00815 new MultiParticleField3D<DenseParticleField3D<T,Descriptor> > ( 00816 management, 00817 defaultMultiBlockPolicy3D().getCombinedStatistics() ); 00818 00819 std::vector<MultiBlock3D*> args; 00820 args.push_back(&fineField); 00821 args.push_back(result); 00822 applyProcessingFunctional ( 00823 new CopyRescaleParticles3D<T,Descriptor>(dxScale,dtScale), 00824 fineField.getBoundingBox(), args ); 00825 00826 return std::auto_ptr<MultiParticleField3D<DenseParticleField3D<T,Descriptor> > >(result); 00827 } 00828 00829 } // namespace plb 00830 00831 #endif // GRID_CONVERSION_3D_HH
1.6.3
1.6.3