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