$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

fdFunctional2D.hh

Go to the documentation of this file.
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