$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 00028 #ifndef FINITE_DIFFERENCE_FUNCTIONAL_2D_HH 00029 #define FINITE_DIFFERENCE_FUNCTIONAL_2D_HH 00030 00031 #include "finiteDifference/fdFunctional2D.h" 00032 #include "core/blockStatistics.h" 00033 #include "core/plbDebug.h" 00034 #include "finiteDifference/fdStencils1D.h" 00035 #include "atomicBlock/atomicBlock2D.h" 00036 #include "atomicBlock/blockLattice2D.h" 00037 #include "atomicBlock/dataField2D.h" 00038 #include <cmath> 00039 00040 namespace plb { 00041 00042 /* ******** BoxXderivativeFunctional2D *********************************** */ 00043 00044 template<typename T> 00045 void BoxXderivativeFunctional2D<T>::processBulk ( 00046 Box2D domain, ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00047 { 00048 Dot2D offset = computeRelativeDisplacement(value, derivative); 00049 00050 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00051 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00052 derivative.get(iX+offset.x, iY+offset.y) = 00053 fd::ctl_diff(value.get(iX+1,iY), value.get(iX-1,iY)); 00054 } 00055 } 00056 } 00057 00058 template<typename T> 00059 void BoxXderivativeFunctional2D<T>::processEdge ( 00060 int direction, int orientation, Box2D domain, 00061 ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00062 { 00063 Dot2D offset = computeRelativeDisplacement(value, derivative); 00064 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00065 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00066 if (direction != 0) { 00067 derivative.get(iX+offset.x, iY+offset.y) = 00068 fd::ctl_diff(value.get(iX+1,iY), value.get(iX-1,iY)); 00069 } 00070 else { 00071 if (orientation == 1) { 00072 derivative.get(iX+offset.x, iY+offset.y) = 00073 fd::o1_fwd_diff(value.get(iX-1,iY), value.get(iX,iY)); 00074 } 00075 else { 00076 derivative.get(iX+offset.x, iY+offset.y) = 00077 fd::o1_fwd_diff(value.get(iX,iY), value.get(iX+1,iY)); 00078 } 00079 } 00080 } 00081 } 00082 } 00083 00084 template<typename T> 00085 void BoxXderivativeFunctional2D<T>::processCorner ( 00086 int normalX, int normalY, Box2D domain, 00087 ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00088 { 00089 Dot2D offset = computeRelativeDisplacement(value, derivative); 00090 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00091 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00092 if (normalX == 1) { 00093 derivative.get(iX+offset.x, iY+offset.y) = 00094 fd::o1_fwd_diff(value.get(iX-1,iY), value.get(iX,iY)); 00095 } 00096 else { 00097 derivative.get(iX+offset.x, iY+offset.y) = 00098 fd::o1_fwd_diff(value.get(iX,iY), value.get(iX+1,iY)); 00099 } 00100 } 00101 } 00102 } 00103 00104 template<typename T> 00105 BoxXderivativeFunctional2D<T>* BoxXderivativeFunctional2D<T>::clone() const 00106 { 00107 return new BoxXderivativeFunctional2D<T>(*this); 00108 } 00109 00110 template<typename T> 00111 void BoxXderivativeFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 00112 modified[0] = modif::nothing; 00113 modified[1] = modif::staticVariables; 00114 } 00115 00116 template<typename T> 00117 BlockDomain::DomainT BoxXderivativeFunctional2D<T>::appliesTo() const { 00118 // Don't apply to envelope, because nearest neighbors need to be accessed. 00119 return BlockDomain::bulk; 00120 } 00121 00122 00123 /* ******** BoxYderivativeFunctional2D *********************************** */ 00124 00125 template<typename T> 00126 void BoxYderivativeFunctional2D<T>::processBulk ( 00127 Box2D domain, ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00128 { 00129 Dot2D offset = computeRelativeDisplacement(value, derivative); 00130 00131 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00132 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00133 derivative.get(iX+offset.x, iY+offset.y) = 00134 fd::ctl_diff(value.get(iX,iY+1), value.get(iX,iY-1)); 00135 } 00136 } 00137 } 00138 00139 template<typename T> 00140 void BoxYderivativeFunctional2D<T>::processEdge ( 00141 int direction, int orientation, Box2D domain, 00142 ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00143 { 00144 Dot2D offset = computeRelativeDisplacement(value, derivative); 00145 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00146 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00147 if (direction != 1) { 00148 derivative.get(iX+offset.x, iY+offset.y) = 00149 fd::ctl_diff(value.get(iX,iY+1), value.get(iX,iY-1)); 00150 } 00151 else { 00152 if (orientation == 1) { 00153 derivative.get(iX+offset.x, iY+offset.y) = 00154 fd::o1_fwd_diff(value.get(iX,iY-1), value.get(iX,iY)); 00155 } 00156 else { 00157 derivative.get(iX+offset.x, iY+offset.y) = 00158 fd::o1_fwd_diff(value.get(iX,iY), value.get(iX,iY+1)); 00159 } 00160 } 00161 } 00162 } 00163 } 00164 00165 template<typename T> 00166 void BoxYderivativeFunctional2D<T>::processCorner ( 00167 int normalX, int normalY, Box2D domain, 00168 ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00169 { 00170 Dot2D offset = computeRelativeDisplacement(value, derivative); 00171 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00172 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00173 if (normalY == 1) { 00174 derivative.get(iX+offset.x, iY+offset.y) = 00175 fd::o1_fwd_diff(value.get(iX,iY-1), value.get(iX,iY)); 00176 } 00177 else { 00178 derivative.get(iX+offset.x, iY+offset.y) = 00179 fd::o1_fwd_diff(value.get(iX,iY), value.get(iX,iY+1)); 00180 } 00181 } 00182 } 00183 } 00184 00185 template<typename T> 00186 BoxYderivativeFunctional2D<T>* BoxYderivativeFunctional2D<T>::clone() const 00187 { 00188 return new BoxYderivativeFunctional2D<T>(*this); 00189 } 00190 00191 template<typename T> 00192 void BoxYderivativeFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 00193 modified[0] = modif::nothing; 00194 modified[1] = modif::staticVariables; 00195 } 00196 00197 template<typename T> 00198 BlockDomain::DomainT BoxYderivativeFunctional2D<T>::appliesTo() const { 00199 // Don't apply to envelope, because nearest neighbors need to be accessed. 00200 return BlockDomain::bulk; 00201 } 00202 00203 /* ******** BoxGradientNormFunctional2D *********************************** */ 00204 00205 template<typename T> 00206 void BoxGradientNormFunctional2D<T>::processBulk ( 00207 Box2D domain, ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00208 { 00209 Dot2D offset = computeRelativeDisplacement(value, derivative); 00210 00211 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00212 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00213 T xDeriv = fdDataField::bulkXderiv (value,iX, iY ); 00214 T yDeriv = fdDataField::bulkYderiv (value,iX, iY ); 00215 T gradientNorm = sqrt(util::sqr(xDeriv)+util::sqr(yDeriv)); 00216 derivative.get(iX+offset.x, iY+offset.y) = gradientNorm; 00217 } 00218 } 00219 } 00220 00221 template<typename T> 00222 void BoxGradientNormFunctional2D<T>::processEdge ( 00223 int direction, int orientation, Box2D domain, 00224 ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00225 { 00226 Dot2D offset = computeRelativeDisplacement(value, derivative); 00227 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00228 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00229 T xDeriv = fdDataField::edgeXderiv (value, direction, orientation, iX, iY ); 00230 T yDeriv = fdDataField::edgeYderiv (value, direction, orientation, iX, iY ); 00231 T gradientNorm = sqrt(util::sqr(xDeriv)+util::sqr(yDeriv)); 00232 derivative.get(iX+offset.x, iY+offset.y) = gradientNorm; 00233 } 00234 } 00235 } 00236 00237 template<typename T> 00238 void BoxGradientNormFunctional2D<T>::processCorner ( 00239 int normalX, int normalY, Box2D domain, 00240 ScalarField2D<T>& value, ScalarField2D<T>& derivative ) 00241 { 00242 Dot2D offset = computeRelativeDisplacement(value, derivative); 00243 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00244 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00245 T xDeriv = fdDataField::cornerXderiv (value, normalX, normalY, iX, iY ); 00246 T yDeriv = fdDataField::cornerYderiv (value, normalX, normalY, iX, iY ); 00247 T gradientNorm = sqrt(util::sqr(xDeriv)+util::sqr(yDeriv)); 00248 derivative.get(iX+offset.x, iY+offset.y) = gradientNorm; 00249 } 00250 } 00251 } 00252 00253 template<typename T> 00254 BoxGradientNormFunctional2D<T>* BoxGradientNormFunctional2D<T>::clone() const 00255 { 00256 return new BoxGradientNormFunctional2D<T>(*this); 00257 } 00258 00259 template<typename T> 00260 void BoxGradientNormFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 00261 modified[0] = modif::nothing; 00262 modified[1] = modif::staticVariables; 00263 } 00264 00265 template<typename T> 00266 BlockDomain::DomainT BoxGradientNormFunctional2D<T>::appliesTo() const { 00267 // Don't apply to envelope, because nearest neighbors need to be accessed. 00268 return BlockDomain::bulk; 00269 } 00270 00271 00272 /* *************** BoxPoissonResidueFunctional2D ********************* */ 00273 00274 template<typename T> 00275 BoxPoissonResidueFunctional2D<T>::BoxPoissonResidueFunctional2D() 00276 : maxResidueId(this->getStatistics().subscribeMax()) 00277 { } 00278 00279 template<typename T> 00280 void BoxPoissonResidueFunctional2D<T>::process ( 00281 Box2D domain, ScalarField2D<T>& pressure, ScalarField2D<T>& rhs ) 00282 { 00283 Dot2D offset = computeRelativeDisplacement(pressure, rhs); 00284 BlockStatistics& statistics = this->getStatistics(); 00285 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00286 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00287 T sumPressure = 00288 pressure.get(iX+1,iY) + 00289 pressure.get(iX,iY+1) + 00290 pressure.get(iX-1,iY) + 00291 pressure.get(iX,iY-1); 00292 T residue = fabs( sumPressure -(T)4*pressure.get(iX,iY) 00293 + rhs.get(iX+offset.x,iY+offset.y) ); 00294 statistics.gatherMax(maxResidueId, residue); 00295 } 00296 } 00297 } 00298 00299 template<typename T> 00300 BoxPoissonResidueFunctional2D<T>* BoxPoissonResidueFunctional2D<T>::clone() const 00301 { 00302 return new BoxPoissonResidueFunctional2D<T>(*this); 00303 } 00304 00305 template<typename T> 00306 T BoxPoissonResidueFunctional2D<T>::getMaxResidue() const { 00307 return this->getStatistics().getMax(maxResidueId); 00308 } 00309 00310 00311 /* ******** BoxPoissonIteration2D ************************************* */ 00312 00313 template<typename T> 00314 BoxPoissonIteration2D<T>::BoxPoissonIteration2D(T beta_) 00315 : beta(beta_) 00316 { } 00317 00318 template<typename T> 00319 void BoxPoissonIteration2D<T>::processBulk ( 00320 Box2D domain, std::vector<ScalarField2D<T>*> scalarFields ) 00321 { 00322 ScalarField2D<T> const& u_h = *scalarFields[0]; 00323 ScalarField2D<T>& new_u_h = *scalarFields[1]; 00324 ScalarField2D<T> const& rhs = *scalarFields[2]; 00325 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00326 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00327 00328 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00329 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00330 T sumPressure = 00331 u_h.get(iX+1,iY) + 00332 u_h.get(iX,iY+1) + 00333 u_h.get(iX-1,iY) + 00334 u_h.get(iX,iY-1); 00335 00336 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00337 ((T)1-beta) * u_h.get(iX,iY) + 00338 (beta/(T)4) * (sumPressure + rhs.get(iX+offset2.x,iY+offset2.y) ); 00339 00340 } 00341 } 00342 } 00343 00344 template<typename T> 00345 void BoxPoissonIteration2D<T>::processEdge ( 00346 int direction, int orientation, Box2D domain, 00347 std::vector<ScalarField2D<T>*> scalarFields ) 00348 { 00349 ScalarField2D<T> const& u_h = *scalarFields[0]; 00350 ScalarField2D<T>& new_u_h = *scalarFields[1]; 00351 ScalarField2D<T> const& rhs = *scalarFields[2]; 00352 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00353 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00354 00355 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00356 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00357 T sumPressure = T(); 00358 if (direction==0 && orientation==1) 00359 sumPressure += u_h.get(iX,iY); 00360 else 00361 sumPressure += u_h.get(iX+1,iY); 00362 00363 if (direction==1 && orientation==1) 00364 sumPressure += u_h.get(iX,iY); 00365 else 00366 sumPressure += u_h.get(iX,iY+1); 00367 00368 if (direction==0 && orientation==-1) 00369 sumPressure += u_h.get(iX,iY); 00370 else 00371 sumPressure += u_h.get(iX-1,iY); 00372 00373 if (direction==1 && orientation==-1) 00374 sumPressure += u_h.get(iX,iY); 00375 else 00376 sumPressure += u_h.get(iX,iY-1); 00377 00378 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00379 ((T)1-beta) * u_h.get(iX,iY) + 00380 (beta/(T)4) * (sumPressure + rhs.get(iX+offset2.x,iY+offset2.y) ); 00381 00382 } 00383 } 00384 } 00385 00386 template<typename T> 00387 void BoxPoissonIteration2D<T>::processCorner ( 00388 int normalX, int normalY, Box2D domain, 00389 std::vector<ScalarField2D<T>*> scalarFields ) 00390 { 00391 ScalarField2D<T> const& u_h = *scalarFields[0]; 00392 ScalarField2D<T>& new_u_h = *scalarFields[1]; 00393 ScalarField2D<T> const& rhs = *scalarFields[2]; 00394 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00395 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00396 00397 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00398 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00399 T sumPressure = T(); 00400 if (normalX==1) 00401 sumPressure += u_h.get(iX,iY); 00402 else 00403 sumPressure += u_h.get(iX+1,iY); 00404 00405 if (normalY==1) 00406 sumPressure += u_h.get(iX,iY); 00407 else 00408 sumPressure += u_h.get(iX,iY+1); 00409 00410 if (normalX==-1) 00411 sumPressure += u_h.get(iX,iY); 00412 else 00413 sumPressure += u_h.get(iX-1,iY); 00414 00415 if (normalY==-1) 00416 sumPressure += u_h.get(iX,iY); 00417 else 00418 sumPressure += u_h.get(iX,iY-1); 00419 00420 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00421 ((T)1-beta) * u_h.get(iX,iY) + 00422 (beta/(T)4) * (sumPressure + rhs.get(iX+offset2.x,iY+offset2.y) ); 00423 00424 } 00425 } 00426 } 00427 00428 template<typename T> 00429 BoxPoissonIteration2D<T>* BoxPoissonIteration2D<T>::clone() const 00430 { 00431 return new BoxPoissonIteration2D<T>(*this); 00432 } 00433 00434 template<typename T> 00435 void BoxPoissonIteration2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 00436 modified[0] = modif::nothing; 00437 modified[1] = modif::staticVariables; 00438 modified[2] = modif::nothing; 00439 } 00440 00441 template<typename T> 00442 BlockDomain::DomainT BoxPoissonIteration2D<T>::appliesTo() const { 00443 // Don't apply to envelope, because nearest neighbors need to be accessed. 00444 return BlockDomain::bulk; 00445 } 00446 00447 /* *************** One Jacobi iteration ************* */ 00448 template<typename T> 00449 void JacobiIteration2D<T>::processBulk ( 00450 Box2D domain, std::vector<ScalarField2D<T>*> scalarFields ) 00451 { 00452 ScalarField2D<T> const& u_h = *scalarFields[0]; 00453 ScalarField2D<T>& new_u_h = *scalarFields[1]; 00454 ScalarField2D<T> const& rhs = *scalarFields[2]; 00455 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00456 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00457 00458 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00459 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00460 T sum_u_h = 00461 u_h.get(iX+1,iY) + 00462 u_h.get(iX,iY+1) + 00463 u_h.get(iX-1,iY) + 00464 u_h.get(iX,iY-1); 00465 00466 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00467 (1.0/4.0) * (sum_u_h - rhs.get(iX+offset2.x,iY+offset2.y) ); 00468 00469 } 00470 } 00471 00472 } 00473 00474 template<typename T> 00475 void JacobiIteration2D<T>::processEdge ( 00476 int direction, int orientation, Box2D domain, 00477 std::vector<ScalarField2D<T>*> scalarFields ) 00478 { 00479 ScalarField2D<T> const& u_h = *scalarFields[0]; 00480 ScalarField2D<T>& new_u_h = *scalarFields[1]; 00481 ScalarField2D<T> const& rhs = *scalarFields[2]; 00482 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00483 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00484 00485 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00486 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00487 T sum = T(); 00488 if (direction==0 && orientation==1) 00489 sum += u_h.get(iX,iY); 00490 else 00491 sum += u_h.get(iX+1,iY); 00492 00493 if (direction==1 && orientation==1) 00494 sum += u_h.get(iX,iY); 00495 else 00496 sum += u_h.get(iX,iY+1); 00497 00498 if (direction==0 && orientation==-1) 00499 sum += u_h.get(iX,iY); 00500 else 00501 sum += u_h.get(iX-1,iY); 00502 00503 if (direction==1 && orientation==-1) 00504 sum += u_h.get(iX,iY); 00505 else 00506 sum += u_h.get(iX,iY-1); 00507 00508 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00509 (1.0/4.0) * (sum - rhs.get(iX+offset2.x,iY+offset2.y) ); 00510 00511 } 00512 } 00513 } 00514 00515 template<typename T> 00516 void JacobiIteration2D<T>::processCorner ( 00517 int normalX, int normalY, Box2D domain, 00518 std::vector<ScalarField2D<T>*> scalarFields ) 00519 { 00520 ScalarField2D<T> const& u_h = *scalarFields[0]; 00521 ScalarField2D<T>& new_u_h = *scalarFields[1]; 00522 ScalarField2D<T> const& rhs = *scalarFields[2]; 00523 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00524 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00525 00526 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00527 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00528 T sumPressure = T(); 00529 if (normalX==1) 00530 sumPressure += u_h.get(iX,iY); 00531 else 00532 sumPressure += u_h.get(iX+1,iY); 00533 00534 if (normalY==1) 00535 sumPressure += u_h.get(iX,iY); 00536 else 00537 sumPressure += u_h.get(iX,iY+1); 00538 00539 if (normalX==-1) 00540 sumPressure += u_h.get(iX,iY); 00541 else 00542 sumPressure += u_h.get(iX-1,iY); 00543 00544 if (normalY==-1) 00545 sumPressure += u_h.get(iX,iY); 00546 else 00547 sumPressure += u_h.get(iX,iY-1); 00548 00549 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00550 (1.0/4.0) * (sumPressure - rhs.get(iX+offset2.x,iY+offset2.y) ); 00551 00552 } 00553 } 00554 } 00555 00556 template<typename T> 00557 JacobiIteration2D<T>* JacobiIteration2D<T>::clone() const 00558 { 00559 return new JacobiIteration2D<T>(); 00560 } 00561 00562 template<typename T> 00563 void JacobiIteration2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 00564 modified[0] = modif::nothing; 00565 modified[1] = modif::staticVariables; 00566 modified[2] = modif::nothing; 00567 } 00568 00569 template<typename T> 00570 BlockDomain::DomainT JacobiIteration2D<T>::appliesTo() const { 00571 // Don't apply to envelope, because nearest neighbors need to be accessed. 00572 return BlockDomain::bulk; 00573 } 00574 00575 /* *************** GaussSeidelIteration2D ****************** */ 00576 template<typename T> 00577 void GaussSeidelIteration2D<T>::processBulk ( 00578 Box2D domain, std::vector<ScalarField2D<T>*> scalarFields ) 00579 { 00580 ScalarField2D<T> const& u_h = *scalarFields[0]; 00581 ScalarField2D<T> const& jacobi_u_h = *scalarFields[1]; 00582 ScalarField2D<T>& new_u_h = *scalarFields[2]; 00583 ScalarField2D<T> const& rhs = *scalarFields[3]; 00584 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00585 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00586 00587 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00588 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00589 T sumPressure = 00590 u_h.get(iX+1,iY) + // t 00591 u_h.get(iX,iY+1) + // t 00592 jacobi_u_h.get(iX-1,iY) + // t+1 00593 jacobi_u_h.get(iX,iY-1); // t+1 00594 00595 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00596 (1/(T)4) * (sumPressure - rhs.get(iX+offset2.x,iY+offset2.y) ); 00597 00598 } 00599 } 00600 } 00601 00602 template<typename T> 00603 void GaussSeidelIteration2D<T>::processEdge ( 00604 int direction, int orientation, Box2D domain, 00605 std::vector<ScalarField2D<T>*> scalarFields ) 00606 { 00607 ScalarField2D<T> const& u_h = *scalarFields[0]; 00608 ScalarField2D<T> const& jacobi_u_h = *scalarFields[1]; 00609 ScalarField2D<T>& new_u_h = *scalarFields[2]; 00610 ScalarField2D<T> const& rhs = *scalarFields[3]; 00611 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00612 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00613 00614 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00615 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00616 T sumPressure = T(); 00617 if (direction==0 && orientation==1) 00618 sumPressure += u_h.get(iX,iY); 00619 else 00620 sumPressure += u_h.get(iX+1,iY); 00621 00622 if (direction==1 && orientation==1) 00623 sumPressure += u_h.get(iX,iY); 00624 else 00625 sumPressure += u_h.get(iX,iY+1); 00626 00627 if (direction==0 && orientation==-1) 00628 sumPressure += u_h.get(iX,iY); 00629 else 00630 sumPressure += jacobi_u_h.get(iX-1,iY); 00631 00632 if (direction==1 && orientation==-1) 00633 sumPressure += u_h.get(iX,iY); 00634 else 00635 sumPressure += jacobi_u_h.get(iX,iY-1); 00636 00637 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00638 (1./4.) * (sumPressure - rhs.get(iX+offset2.x,iY+offset2.y) ); 00639 00640 } 00641 } 00642 } 00643 00644 template<typename T> 00645 void GaussSeidelIteration2D<T>::processCorner ( 00646 int normalX, int normalY, Box2D domain, 00647 std::vector<ScalarField2D<T>*> scalarFields ) 00648 { 00649 ScalarField2D<T> const& u_h = *scalarFields[0]; 00650 ScalarField2D<T> const& jacobi_u_h = *scalarFields[1]; 00651 ScalarField2D<T>& new_u_h = *scalarFields[2]; 00652 ScalarField2D<T> const& rhs = *scalarFields[3]; 00653 Dot2D offset1 = computeRelativeDisplacement(u_h, new_u_h); 00654 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00655 00656 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00657 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00658 T sumPressure = T(); 00659 if (normalX==1) 00660 sumPressure += u_h.get(iX,iY); 00661 else 00662 sumPressure += u_h.get(iX+1,iY); 00663 00664 if (normalY==1) 00665 sumPressure += u_h.get(iX,iY); 00666 else 00667 sumPressure += u_h.get(iX,iY+1); 00668 00669 if (normalX==-1) 00670 sumPressure += u_h.get(iX,iY); 00671 else 00672 sumPressure += jacobi_u_h.get(iX-1,iY); 00673 00674 if (normalY==-1) 00675 sumPressure += u_h.get(iX,iY); 00676 else 00677 sumPressure += jacobi_u_h.get(iX,iY-1); 00678 00679 new_u_h.get(iX+offset1.x,iY+offset1.y) = 00680 (1./4.) * (sumPressure - rhs.get(iX+offset2.x,iY+offset2.y) ); 00681 00682 } 00683 } 00684 } 00685 00686 template<typename T> 00687 GaussSeidelIteration2D<T>* GaussSeidelIteration2D<T>::clone() const 00688 { 00689 return new GaussSeidelIteration2D<T>(); 00690 } 00691 00692 template<typename T> 00693 void GaussSeidelIteration2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 00694 modified[0] = modif::nothing; 00695 modified[1] = modif::nothing; 00696 modified[2] = modif::staticVariables; 00697 modified[3] = modif::nothing; 00698 } 00699 00700 template<typename T> 00701 BlockDomain::DomainT GaussSeidelIteration2D<T>::appliesTo() const { 00702 // Don't apply to envelope, because nearest neighbors need to be accessed. 00703 return BlockDomain::bulk; 00704 } 00705 00706 /* *************** Gauss-Seidel defect (d_h) ****************** */ 00707 template<typename T> 00708 void GaussSeidelDefect2D<T>::processBulk( Box2D domain, std::vector<ScalarField2D<T>*> scalarFields){ 00709 ScalarField2D<T> const& u_h = *scalarFields[0]; 00710 ScalarField2D<T>& d_h = *scalarFields[1]; 00711 ScalarField2D<T> const& rhs = *scalarFields[2]; 00712 00713 Dot2D offset1 = computeRelativeDisplacement(u_h, d_h); 00714 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00715 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00716 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00717 // Apply laplacien operator to u_h 00718 T discreteLaplacien_u_h = 00719 u_h.get(iX+1,iY) + 00720 u_h.get(iX,iY+1) + 00721 u_h.get(iX-1,iY) + 00722 u_h.get(iX,iY-1) - 00723 4.*u_h.get(iX,iY); 00724 // compute the defect for the (iX,iY) point 00725 d_h.get(iX+offset1.x,iY+offset1.y) = 00726 discreteLaplacien_u_h - rhs.get(iX+offset2.x,iY+offset2.y) ; 00727 00728 } 00729 } 00730 } 00731 00732 template<typename T> 00733 void GaussSeidelDefect2D<T>::processEdge ( 00734 int direction, int orientation, Box2D domain, 00735 std::vector<ScalarField2D<T>*> scalarFields ) 00736 { 00737 ScalarField2D<T> const& u_h = *scalarFields[0]; 00738 ScalarField2D<T>& d_h = *scalarFields[1]; 00739 ScalarField2D<T> const& rhs = *scalarFields[2]; 00740 00741 Dot2D offset1 = computeRelativeDisplacement(u_h, d_h); 00742 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00743 00744 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00745 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00746 T sumPressure = T(); 00747 if (direction==0 && orientation==1) 00748 sumPressure += u_h.get(iX,iY); 00749 else 00750 sumPressure += u_h.get(iX+1,iY); 00751 00752 if (direction==1 && orientation==1) 00753 sumPressure += u_h.get(iX,iY); 00754 else 00755 sumPressure += u_h.get(iX,iY+1); 00756 00757 if (direction==0 && orientation==-1) 00758 sumPressure += u_h.get(iX,iY); 00759 else 00760 sumPressure += u_h.get(iX-1,iY); 00761 00762 if (direction==1 && orientation==-1) 00763 sumPressure += u_h.get(iX,iY); 00764 else 00765 sumPressure += u_h.get(iX,iY-1); 00766 00767 d_h.get(iX+offset1.x,iY+offset1.y) = 00768 sumPressure-4.0*u_h.get(iX,iY) - rhs.get(iX+offset2.x,iY+offset2.y) ; 00769 00770 } 00771 } 00772 } 00773 00774 template<typename T> 00775 void GaussSeidelDefect2D<T>::processCorner ( 00776 int normalX, int normalY, Box2D domain, 00777 std::vector<ScalarField2D<T>*> scalarFields ) 00778 { 00779 ScalarField2D<T> const& u_h = *scalarFields[0]; 00780 ScalarField2D<T>& d_h = *scalarFields[1]; 00781 ScalarField2D<T> const& rhs = *scalarFields[2]; 00782 00783 Dot2D offset1 = computeRelativeDisplacement(u_h, d_h); 00784 Dot2D offset2 = computeRelativeDisplacement(u_h, rhs); 00785 00786 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00787 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00788 T sumPressure = T(); 00789 if (normalX==1) 00790 sumPressure += u_h.get(iX,iY); 00791 else 00792 sumPressure += u_h.get(iX+1,iY); 00793 00794 if (normalY==1) 00795 sumPressure += u_h.get(iX,iY); 00796 else 00797 sumPressure += u_h.get(iX,iY+1); 00798 00799 if (normalX==-1) 00800 sumPressure += u_h.get(iX,iY); 00801 else 00802 sumPressure += u_h.get(iX-1,iY); 00803 00804 if (normalY==-1) 00805 sumPressure += u_h.get(iX,iY); 00806 else 00807 sumPressure += u_h.get(iX,iY-1); 00808 00809 d_h.get(iX+offset1.x,iY+offset1.y) = 00810 sumPressure-4.0*u_h.get(iX,iY) - rhs.get(iX+offset2.x,iY+offset2.y) ; 00811 00812 } 00813 } 00814 } 00815 00816 00817 00818 template<typename T> 00819 GaussSeidelDefect2D<T>* GaussSeidelDefect2D<T>::clone() const { 00820 return new GaussSeidelDefect2D(); 00821 } 00822 00823 template<typename T> 00824 void GaussSeidelDefect2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const{ 00825 modified[0] = modif::nothing; 00826 modified[1] = modif::staticVariables; 00827 modified[2] = modif::nothing; 00828 } 00829 00830 template<typename T> 00831 BlockDomain::DomainT GaussSeidelDefect2D<T>::appliesTo() const{ 00832 return BlockDomain::bulk; 00833 } 00834 00835 /* *************** Max of Gauss-Seidel defect (max(d_h)) ****************** */ 00836 template<typename T> 00837 GaussSeidelMaxDefectFunctional2D<T>::GaussSeidelMaxDefectFunctional2D() 00838 : maxResidueId(this->getStatistics().subscribeMax()) 00839 { } 00840 00841 template<typename T> 00842 void GaussSeidelMaxDefectFunctional2D<T>::process ( 00843 Box2D domain, ScalarField2D<T>& u_h, ScalarField2D<T>& rhs ) 00844 { 00845 Dot2D offset = computeRelativeDisplacement(u_h, rhs); 00846 BlockStatistics& statistics = this->getStatistics(); 00847 for (plint iX=domain.x0; iX<=domain.x1; ++iX) { 00848 for (plint iY=domain.y0; iY<=domain.y1; ++iY) { 00849 T discreteLaplacien_u_h = 00850 u_h.get(iX+1,iY) + 00851 u_h.get(iX,iY+1) + 00852 u_h.get(iX-1,iY) + 00853 u_h.get(iX,iY-1) - 00854 4.*u_h.get(iX,iY); 00855 // compute the absolute value of the residue 00856 T residue = fabs ( discreteLaplacien_u_h - rhs.get(iX+offset.x,iY+offset.y) ); 00857 // save it in the internal statistics 00858 statistics.gatherMax(maxResidueId, residue); 00859 } 00860 } 00861 } 00862 00863 template<typename T> 00864 GaussSeidelMaxDefectFunctional2D<T>* GaussSeidelMaxDefectFunctional2D<T>::clone() const 00865 { 00866 return new GaussSeidelMaxDefectFunctional2D<T>(*this); 00867 } 00868 00869 template<typename T> 00870 T GaussSeidelMaxDefectFunctional2D<T>::getMaxResidual() const { 00871 return this->getStatistics().getMax(maxResidueId); 00872 } 00873 00874 00875 00876 } // namespace plb 00877 00878 #endif // FINITE_DIFFERENCE_FUNCTIONAL_2D_HH
1.6.3
1.6.3