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

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