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

dataAnalysisFunctional3D.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 DATA_ANALYSIS_FUNCTIONAL_3D_HH
00029 #define DATA_ANALYSIS_FUNCTIONAL_3D_HH
00030 
00031 #include "dataProcessors/dataAnalysisFunctional3D.h"
00032 #include "core/plbDebug.h"
00033 #include "core/util.h"
00034 #include "core/blockStatistics.h"
00035 #include "latticeBoltzmann/momentTemplates.h"
00036 #include "latticeBoltzmann/geometricOperationTemplates.h"
00037 #include "finiteDifference/fdStencils1D.h"
00038 #include "atomicBlock/atomicBlock3D.h"
00039 #include "atomicBlock/blockLattice3D.h"
00040 #include "atomicBlock/dataField3D.h"
00041 #include <cmath>
00042 #include <limits>
00043 
00044 namespace plb {
00045 
00047 namespace fdLattice {
00048 
00049 template<typename T, template<typename U> class Descriptor> 
00050 inline Array<T,3> firstOrderBulkVorticity (
00051         BlockLattice3D<T,Descriptor> const& lattice, plint iX, plint iY, plint iZ )
00052 {
00053     Array<T,3> u000;
00054     lattice.get(iX  ,iY  ,iZ  ).computeVelocity(u000);
00055     Array<T,3> u001;
00056     lattice.get(iX  ,iY  ,iZ+1).computeVelocity(u001);
00057     Array<T,3> u010;
00058     lattice.get(iX  ,iY+1,iZ  ).computeVelocity(u010);
00059     Array<T,3> u100;
00060     lattice.get(iX+1,iY  ,iZ  ).computeVelocity(u100);
00061 
00062     Array<T,3> vorticity;
00063     T dyuz = u010[2] - u000[2];
00064     T dzuy = u001[1] - u000[1];
00065     vorticity[0] = dyuz - dzuy;
00066 
00067     T dzux = u001[0] - u000[0];
00068     T dxuz = u100[2] - u000[2];
00069     vorticity[1] = dzux - dxuz;
00070 
00071     T dxuy = u100[1] - u000[1];
00072     T dyux = u010[0] - u000[0];
00073     vorticity[2] = dxuy - dyux;
00074 
00075     return vorticity;
00076 }
00077 
00078 }  // fdLattice
00079 
00080 
00082 namespace fdDataField {
00083 
00084 template<typename T>
00085 inline T bulkXderiv (
00086         ScalarField3D<T> const& field, plint iX, plint iY, plint iZ )
00087 {
00088     T dxu = fd::ctl_diff( field.get(iX+1,iY,iZ),
00089                           field.get(iX-1,iY,iZ) );
00090     return dxu;
00091 }
00092 
00093 template<typename T>
00094 inline T bulkYderiv (
00095         ScalarField3D<T> const& field, plint iX, plint iY, plint iZ )
00096 {
00097     T dyu = fd::ctl_diff( field.get(iX,iY+1,iZ),
00098                           field.get(iX,iY-1,iZ) );
00099     return dyu;
00100 }
00101 
00102 template<typename T>
00103 inline T bulkZderiv (
00104         ScalarField3D<T> const& field, plint iX, plint iY, plint iZ )
00105 {
00106     T dzu = fd::ctl_diff( field.get(iX,iY,iZ+1),
00107                           field.get(iX,iY,iZ-1) );
00108     return dzu;
00109 }
00110 
00111 template<typename T>
00112 inline T planeXderiv (
00113         ScalarField3D<T> const& field, int direction, int orientation,
00114         plint iX, plint iY, plint iZ )
00115 {
00116     if (direction==0) {
00117         return -orientation *
00118             fd::o1_fwd_diff( field.get(iX              ,iY,iZ),
00119                              field.get(iX-1*orientation,iY,iZ) );
00120     }
00121     else {
00122         return bulkXderiv(field, iX,iY,iZ);
00123     }
00124 }
00125 
00126 template<typename T>
00127 inline T planeYderiv (
00128         ScalarField3D<T> const& field, int direction, int orientation,
00129         plint iX, plint iY, plint iZ )
00130 {
00131     if (direction==1) {
00132         return -orientation *
00133             fd::o1_fwd_diff( field.get(iX,iY              ,iZ),
00134                              field.get(iX,iY-1*orientation,iZ) );
00135     }
00136     else {
00137         return bulkYderiv(field, iX,iY,iZ);
00138     }
00139 }
00140 
00141 template<typename T>
00142 inline T planeZderiv (
00143         ScalarField3D<T> const& field, int direction, int orientation,
00144         plint iX, plint iY, plint iZ )
00145 {
00146     if (direction==2) {
00147         return -orientation *
00148             fd::o1_fwd_diff( field.get(iX,iY,iZ              ),
00149                              field.get(iX,iY,iZ-1*orientation) );
00150     }
00151     else {
00152         return bulkZderiv(field, iX,iY,iZ);
00153     }
00154 }
00155 
00156 template<typename T>
00157 inline T edgeXderiv (
00158         ScalarField3D<T> const& field,
00159         int plane, int direction1, int direction2,
00160         plint iX, plint iY, plint iZ )
00161 {
00162     if (plane==0) {
00163         return bulkXderiv(field, iX,iY,iZ);
00164     }
00165     else {
00166         int orientation = plane==1 ? direction2 : direction1;
00167         return -orientation *
00168             fd::o1_fwd_diff( field.get(iX              ,iY,iZ),
00169                              field.get(iX-1*orientation,iY,iZ) );
00170     }
00171 }
00172 
00173 template<typename T>
00174 inline T edgeYderiv (
00175         ScalarField3D<T> const& field,
00176         int plane, int direction1, int direction2,
00177         plint iX, plint iY, plint iZ )
00178 {
00179     if (plane==1) {
00180         return bulkYderiv(field, iX,iY,iZ);
00181     }
00182     else {
00183         int orientation = plane==0 ? direction1 : direction2;
00184         return -orientation *
00185             fd::o1_fwd_diff( field.get(iX,iY              ,iZ),
00186                              field.get(iX,iY-1*orientation,iZ) );
00187     }
00188 }
00189 
00190 template<typename T>
00191 inline T edgeZderiv (
00192         ScalarField3D<T> const& field,
00193         int plane, int direction1, int direction2,
00194         plint iX, plint iY, plint iZ )
00195 {
00196     if (plane==2) {
00197         return bulkZderiv(field, iX,iY,iZ);
00198     }
00199     else {
00200         int orientation = plane==0 ? direction2 : direction1;
00201         return -orientation *
00202             fd::o1_fwd_diff( field.get(iX,iY,iZ              ),
00203                              field.get(iX,iY,iZ-1*orientation) );
00204     }
00205 }
00206 
00207 template<typename T>
00208 inline T cornerXderiv (
00209         ScalarField3D<T> const& field,
00210         int normalX, int normalY, int normalZ,
00211         plint iX, plint iY, plint iZ )
00212 {
00213     int orientation = normalX;
00214     return -orientation *
00215         fd::o1_fwd_diff( field.get(iX              ,iY,iZ),
00216                          field.get(iX-1*orientation,iY,iZ) );
00217 }
00218 
00219 template<typename T>
00220 inline T cornerYderiv (
00221         ScalarField3D<T> const& field,
00222         int normalX, int normalY, int normalZ,
00223         plint iX, plint iY, plint iZ )
00224 {
00225     int orientation = normalY;
00226     return -orientation *
00227         fd::o1_fwd_diff( field.get(iX,iY              ,iZ),
00228                          field.get(iX,iY-1*orientation,iZ) );
00229 }
00230 
00231 template<typename T>
00232 inline T cornerZderiv (
00233         ScalarField3D<T> const& field,
00234         int normalX, int normalY, int normalZ,
00235         plint iX, plint iY, plint iZ )
00236 {
00237     int orientation = normalZ;
00238     return -orientation *
00239         fd::o1_fwd_diff( field.get(iX,iY,iZ              ),
00240                          field.get(iX,iY,iZ-1*orientation) );
00241 }
00242 
00243 }  // fdDataField
00244 
00245 /* *************** PART I ******************************************** */
00246 /* *************** Analysis of the block-lattice ********************* */
00247 /* ******************************************************************* */
00248 
00249 /* *************** Reductive Data Functionals for BlockLattice ******* */
00250 
00251 template<typename T, template<typename U> class Descriptor> 
00252 BoxSumRhoBarFunctional3D<T,Descriptor>::BoxSumRhoBarFunctional3D()
00253     : sumRhoBarId(this->getStatistics().subscribeSum())
00254 { }
00255 
00256 template<typename T, template<typename U> class Descriptor> 
00257 void BoxSumRhoBarFunctional3D<T,Descriptor>::process (
00258         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00259 {
00260     BlockStatistics& statistics = this->getStatistics();
00261     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00262         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00263             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00264                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
00265                 statistics.gatherSum (
00266                         sumRhoBarId, cell.getDynamics().computeRhoBar(cell)
00267                 );
00268             }
00269         }
00270     }
00271 }
00272 
00273 template<typename T, template<typename U> class Descriptor> 
00274 BoxSumRhoBarFunctional3D<T,Descriptor>*
00275     BoxSumRhoBarFunctional3D<T,Descriptor>::clone() const
00276 {
00277     return new BoxSumRhoBarFunctional3D(*this);
00278 }
00279 
00280 template<typename T, template<typename U> class Descriptor> 
00281 T BoxSumRhoBarFunctional3D<T,Descriptor>::getSumRhoBar() const {
00282     return this->getStatistics().getSum(sumRhoBarId);
00283 }
00284 
00285 
00286 template<typename T, template<typename U> class Descriptor> 
00287 BoxSumEnergyFunctional3D<T,Descriptor>::BoxSumEnergyFunctional3D()
00288     : sumEnergyId(this->getStatistics().subscribeSum())
00289 { }
00290 
00291 template<typename T, template<typename U> class Descriptor> 
00292 void BoxSumEnergyFunctional3D<T,Descriptor>::process (
00293         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00294 {
00295     BlockStatistics& statistics = this->getStatistics();
00296     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00297         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00298             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00299                 Array<T,Descriptor<T>::d> velocity;
00300                 lattice.get(iX,iY,iZ).computeVelocity(velocity);
00301                 T uNormSqr = VectorTemplate<T,Descriptor>::normSqr(velocity);
00302                 statistics.gatherSum(sumEnergyId, uNormSqr);
00303             }
00304         }
00305     }
00306 }
00307 
00308 template<typename T, template<typename U> class Descriptor> 
00309 BoxSumEnergyFunctional3D<T,Descriptor>*
00310     BoxSumEnergyFunctional3D<T,Descriptor>::clone() const
00311 {
00312     return new BoxSumEnergyFunctional3D(*this);
00313 }
00314 
00315 template<typename T, template<typename U> class Descriptor> 
00316 T BoxSumEnergyFunctional3D<T,Descriptor>::getSumEnergy() const {
00317     return this->getStatistics().getSum(sumEnergyId) / (T)2;
00318 }
00319 
00320 template<typename T, template<typename U> class Descriptor> 
00321 void BoxSumEnergyFunctional3D<T,Descriptor>::getDimensionsX(std::vector<int>& dimensions) const
00322 {
00323     dimensions.resize(1);
00324     dimensions[0] = 2;
00325 }
00326 
00327 template<typename T, template<typename U> class Descriptor> 
00328 void BoxSumEnergyFunctional3D<T,Descriptor>::getDimensionsT(std::vector<int>& dimensions) const
00329 {
00330     dimensions.resize(1);
00331     dimensions[0] = -2;
00332 }
00333 
00334 
00335 /* ******** DensitySingleProbe3D *********************************** */
00336 
00337 template<typename T, template<typename U> class Descriptor>
00338 DensitySingleProbe3D<T,Descriptor>::DensitySingleProbe3D (
00339         std::vector<Array<T,3> > const& positions_ )
00340     : positions(positions_)
00341 {
00342     densityIds.resize(positions.size());
00343     for (pluint i=0; i<positions.size(); ++i) {
00344         densityIds[i] = this->getStatistics().subscribeSum();
00345     }
00346 }
00347 
00348 template<typename T, template<typename U> class Descriptor>
00349 void DensitySingleProbe3D<T,Descriptor>::process (
00350         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00351 {
00352     std::vector<Dot3D> cellPos(8);
00353     std::vector<T> weights(8);
00354     T density;
00355     for (pluint i=0; i<positions.size(); ++i) {
00356         density=0.;
00357         Array<T,3> position(positions[i]);
00358         Dot3D referenceCellPos((plint)position[0], (plint)position[1], (plint)position[2]);
00359         referenceCellPos -= lattice.getLocation();
00360         if (contained(referenceCellPos, domain)) {
00361             linearInterpolationCoefficients(lattice, position, cellPos, weights);
00362             for (plint iCell=0; iCell<8; ++iCell) {
00363                 Cell<T,Descriptor> const& cell = lattice.get(cellPos[iCell].x,cellPos[iCell].y,cellPos[iCell].z);
00364                 T cellDensity = cell.computeDensity();
00365                 density+=weights[iCell]*cellDensity;
00366             }
00367         }
00368        this->getStatistics().gatherSum(densityIds[i], density);
00369     }
00370 }
00371 
00372 template<typename T, template<typename U> class Descriptor>
00373 DensitySingleProbe3D<T,Descriptor>*
00374     DensitySingleProbe3D<T,Descriptor>::clone() const
00375 {
00376     return new DensitySingleProbe3D<T,Descriptor>(*this);
00377 }
00378 
00379 template<typename T, template<typename U> class Descriptor>
00380 std::vector<T> DensitySingleProbe3D<T,Descriptor>::getDensities() const {
00381     std::vector<T> densities(positions.size());
00382     for (pluint i=0; i<positions.size(); ++i) {
00383         densities[i] = this->getStatistics().getSum(densityIds[i]);
00384     }
00385     return densities;
00386 }
00387 
00388 
00389 /* ******** VelocitySingleProbe3D *********************************** */
00390 
00391 template<typename T, template<typename U> class Descriptor>
00392 VelocitySingleProbe3D<T,Descriptor>::VelocitySingleProbe3D (
00393         std::vector<Array<T,3> > const& positions_ )
00394     : positions(positions_)
00395 {
00396     velIds.resize(positions.size());
00397     for (pluint iVel=0; iVel<positions.size(); ++iVel) {
00398         velIds[iVel][0] = this->getStatistics().subscribeSum();
00399         velIds[iVel][1] = this->getStatistics().subscribeSum();
00400         velIds[iVel][2] = this->getStatistics().subscribeSum();
00401     }
00402 }
00403 
00404 template<typename T, template<typename U> class Descriptor>
00405 void VelocitySingleProbe3D<T,Descriptor>::process (
00406         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00407 {
00408     std::vector<Dot3D> cellPos(8);
00409     std::vector<T> weights(8);
00410     Array<T,3> velocity;
00411     for (pluint iVel=0; iVel<positions.size(); ++iVel) {
00412         velocity.resetToZero();
00413         Array<T,3> position(positions[iVel]);
00414         Dot3D referenceCellPos((plint)position[0], (plint)position[1], (plint)position[2]);
00415         referenceCellPos -= lattice.getLocation();
00416         if (contained(referenceCellPos, domain)) {
00417             linearInterpolationCoefficients(lattice, position, cellPos, weights);
00418             for (plint iCell=0; iCell<8; ++iCell) {
00419                 Cell<T,Descriptor> const& cell = lattice.get(cellPos[iCell].x,cellPos[iCell].y,cellPos[iCell].z);
00420                 Array<T,3> cellVelocity;
00421                 cell.computeVelocity(cellVelocity);
00422                 velocity+=weights[iCell]*cellVelocity;
00423             }
00424         }
00425        this->getStatistics().gatherSum(velIds[iVel][0], velocity[0]);
00426        this->getStatistics().gatherSum(velIds[iVel][1], velocity[1]);
00427        this->getStatistics().gatherSum(velIds[iVel][2], velocity[2]);
00428     }
00429 }
00430 
00431 template<typename T, template<typename U> class Descriptor>
00432 VelocitySingleProbe3D<T,Descriptor>*
00433     VelocitySingleProbe3D<T,Descriptor>::clone() const
00434 {
00435     return new VelocitySingleProbe3D<T,Descriptor>(*this);
00436 }
00437 
00438 template<typename T, template<typename U> class Descriptor>
00439 std::vector<Array<T,3> > VelocitySingleProbe3D<T,Descriptor>::getVelocities() const {
00440     std::vector<Array<T,3> > velocities(positions.size());
00441     for (pluint iVel=0; iVel<positions.size(); ++iVel) {
00442         velocities[iVel][0] = this->getStatistics().getSum(velIds[iVel][0]);
00443         velocities[iVel][1] = this->getStatistics().getSum(velIds[iVel][1]);
00444         velocities[iVel][2] = this->getStatistics().getSum(velIds[iVel][2]);
00445     }
00446     return velocities;
00447 }
00448 
00449 
00450 /* ******** VorticitySingleProbe3D *********************************** */
00451 
00452 template<typename T, template<typename U> class Descriptor>
00453 VorticitySingleProbe3D<T,Descriptor>::VorticitySingleProbe3D (
00454         std::vector<Array<T,3> > const& positions_ )
00455     : positions(positions_)
00456 {
00457     vorticityIds.resize(positions.size());
00458     for (pluint iVel=0; iVel<positions.size(); ++iVel) {
00459         vorticityIds[iVel][0] = this->getStatistics().subscribeSum();
00460         vorticityIds[iVel][1] = this->getStatistics().subscribeSum();
00461         vorticityIds[iVel][2] = this->getStatistics().subscribeSum();
00462     }
00463 }
00464 
00465 template<typename T, template<typename U> class Descriptor>
00466 void VorticitySingleProbe3D<T,Descriptor>::process (
00467         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00468 {
00469     Array<T,3> vorticity;
00470     for (pluint iVort=0; iVort<positions.size(); ++iVort) {
00471         vorticity.resetToZero();
00472         Array<T,3> position(positions[iVort]);
00473         Dot3D referenceCellPos((plint)position[0], (plint)position[1], (plint)position[2]);
00474         referenceCellPos -= lattice.getLocation();
00475         if (contained(referenceCellPos, domain)) {
00476             vorticity = fdLattice::firstOrderBulkVorticity(lattice, referenceCellPos.x, referenceCellPos.y, referenceCellPos.z);
00477         }
00478        this->getStatistics().gatherSum(vorticityIds[iVort][0], vorticity[0]);
00479        this->getStatistics().gatherSum(vorticityIds[iVort][1], vorticity[1]);
00480        this->getStatistics().gatherSum(vorticityIds[iVort][2], vorticity[2]);
00481     }
00482 }
00483 
00484 template<typename T, template<typename U> class Descriptor>
00485 VorticitySingleProbe3D<T,Descriptor>*
00486     VorticitySingleProbe3D<T,Descriptor>::clone() const
00487 {
00488     return new VorticitySingleProbe3D<T,Descriptor>(*this);
00489 }
00490 
00491 template<typename T, template<typename U> class Descriptor>
00492 std::vector<Array<T,3> > VorticitySingleProbe3D<T,Descriptor>::getVorticities() const {
00493     std::vector<Array<T,3> > vorticities(positions.size());
00494     for (pluint iVort=0; iVort<positions.size(); ++iVort) {
00495         vorticities[iVort][0] = this->getStatistics().getSum(vorticityIds[iVort][0]);
00496         vorticities[iVort][1] = this->getStatistics().getSum(vorticityIds[iVort][1]);
00497         vorticities[iVort][2] = this->getStatistics().getSum(vorticityIds[iVort][2]);
00498     }
00499     return vorticities;
00500 }
00501 
00502 
00503 /* *************** Data Functionals for BlockLattice ***************** */
00504 
00505 template<typename T, template<typename U> class Descriptor> 
00506 void CopyPopulationsFunctional3D<T,Descriptor>::process (
00507         Box3D domain, BlockLattice3D<T,Descriptor>& latticeFrom,
00508                       BlockLattice3D<T,Descriptor>& latticeTo )
00509 {
00510     Dot3D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00511     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00512         plint ofX = iX + offset.x;
00513         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00514             plint ofY = iY + offset.y;
00515             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00516                 latticeTo.get(ofX,ofY,iZ+offset.z).
00517                     attributeValues(latticeFrom.get(iX,iY,iZ));
00518             }
00519         }
00520     }
00521 }
00522 
00523 template<typename T, template<typename U> class Descriptor> 
00524 CopyPopulationsFunctional3D<T,Descriptor>* CopyPopulationsFunctional3D<T,Descriptor>::clone() const
00525 {
00526     return new CopyPopulationsFunctional3D<T,Descriptor>(*this);
00527 }
00528 
00529 template<typename T, template<typename U> class Descriptor> 
00530 void CopyPopulationsFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00531     modified[0] = modif::nothing;
00532     modified[1] = modif::staticVariables;
00533 }
00534 
00535 template<typename T, template<typename U> class Descriptor> 
00536 BlockDomain::DomainT CopyPopulationsFunctional3D<T,Descriptor>::appliesTo() const {
00537     return BlockDomain::bulkAndEnvelope;
00538 }
00539 
00540 template<typename T1, template<typename U1> class Descriptor1, typename T2, template<typename U2> class Descriptor2> 
00541 void CopyConvertPopulationsFunctional3D<T1,Descriptor1, T2,Descriptor2>::process (
00542     Box3D domain, BlockLattice3D<T1,Descriptor1>& latticeFrom,
00543     BlockLattice3D<T2,Descriptor2>& latticeTo )
00544 {
00545     Dot3D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00546     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00547         plint ofX = iX + offset.x;
00548         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00549             plint ofY = iY + offset.y;
00550             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00551                     latticeTo.get(ofX,ofY,iZ+offset.z).
00552                     attributeValues(latticeFrom.get(iX,iY,iZ));
00553             }
00554         }
00555     }
00556 }
00557 
00558 template<typename T1, template<typename U1> class Descriptor1, typename T2, template<typename U2> class Descriptor2> 
00559 CopyConvertPopulationsFunctional3D<T1,Descriptor1,T2,Descriptor2>* CopyConvertPopulationsFunctional3D<T1,Descriptor1,T2,Descriptor2>::clone() const
00560 {
00561     return new CopyConvertPopulationsFunctional3D<T1,Descriptor1,T2,Descriptor2>(*this);
00562 }
00563 
00564 template<typename T1, template<typename U1> class Descriptor1, typename T2, template<typename U2> class Descriptor2> 
00565 void CopyConvertPopulationsFunctional3D<T1,Descriptor1,T2,Descriptor2>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00566     modified[0] = modif::nothing;
00567     modified[1] = modif::staticVariables;
00568 }
00569 
00570 template<typename T1, template<typename U1> class Descriptor1, typename T2, template<typename U2> class Descriptor2> 
00571 BlockDomain::DomainT CopyConvertPopulationsFunctional3D<T1,Descriptor1,T2,Descriptor2>::appliesTo() const {
00572     return BlockDomain::bulkAndEnvelope;
00573 }
00574 
00575 
00576 template<typename T, template<typename U> class Descriptor> 
00577 void LatticeCopyAllFunctional3D<T,Descriptor>::process (
00578         Box3D domain, BlockLattice3D<T,Descriptor>& latticeFrom,
00579                       BlockLattice3D<T,Descriptor>& latticeTo )
00580 {
00581     std::vector<char> data;
00582     Dot3D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00583     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00584         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00585             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00586                 Cell<T,Descriptor> const& fromCell = latticeFrom.get(iX,iY,iZ);
00587                 Cell<T,Descriptor>& toCell = latticeTo.get(iX+offset.x,iY+offset.y,iZ+offset.z);
00588                 toCell.attributeValues(fromCell);
00589 
00590                 data.clear();
00591                 HierarchicSerializer serializer(data, fromCell.getDynamics().getId());
00592                 fromCell.getDynamics().serialize(serializer);
00593 
00594                 HierarchicUnserializer unSerializer(data, 0);
00595                 toCell.getDynamics().unserialize(unSerializer);
00596             }
00597         }
00598     }
00599 }
00600 
00601 template<typename T, template<typename U> class Descriptor> 
00602 LatticeCopyAllFunctional3D<T,Descriptor>* LatticeCopyAllFunctional3D<T,Descriptor>::clone() const
00603 {
00604     return new LatticeCopyAllFunctional3D<T,Descriptor>(*this);
00605 }
00606 
00607 template<typename T, template<typename U> class Descriptor> 
00608 void LatticeCopyAllFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00609     modified[0] = modif::nothing;
00610     modified[1] = modif::staticVariables;
00611 }
00612 
00613 template<typename T, template<typename U> class Descriptor> 
00614 BlockDomain::DomainT LatticeCopyAllFunctional3D<T,Descriptor>::appliesTo() const {
00615     return BlockDomain::bulkAndEnvelope;
00616 }
00617 
00618 
00619 
00620 template<typename T, template<typename U> class Descriptor> 
00621 void LatticeRegenerateFunctional3D<T,Descriptor>::process (
00622         Box3D domain, BlockLattice3D<T,Descriptor>& latticeFrom,
00623                       BlockLattice3D<T,Descriptor>& latticeTo )
00624 {
00625     Dot3D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00626     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00627         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00628             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00629                 latticeTo.get(iX+offset.x,iY+offset.y,iZ+offset.z).attributeValues(latticeFrom.get(iX,iY,iZ));
00630                 latticeTo.attributeDynamics(iX+offset.x,iY+offset.y,iZ+offset.z,
00631                                            latticeFrom.get(iX,iY,iZ).getDynamics().clone());
00632                 latticeTo.get(iX+offset.x,iY+offset.y,iZ+offset.z).
00633                     attributeValues(latticeFrom.get(iX,iY,iZ));
00634             }
00635         }
00636     }
00637 }
00638 
00639 template<typename T, template<typename U> class Descriptor> 
00640 LatticeRegenerateFunctional3D<T,Descriptor>* LatticeRegenerateFunctional3D<T,Descriptor>::clone() const
00641 {
00642     return new LatticeRegenerateFunctional3D<T,Descriptor>(*this);
00643 }
00644 
00645 template<typename T, template<typename U> class Descriptor> 
00646 void LatticeRegenerateFunctional3D<T,Descriptor>::getTypeOfModification (
00647         std::vector<modif::ModifT>& modified ) const
00648 {
00649     modified[0] = modif::nothing;
00650     // Full dynamics object must be recreated, because this data processor
00651     //   re-attributes a new dynamics and acts on the bulk only.
00652     modified[1] = modif::dataStructure;
00653 }
00654 
00655 template<typename T, template<typename U> class Descriptor> 
00656 void BoxDensityFunctional3D<T,Descriptor>::process (
00657         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
00658 {
00659     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
00660     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00661         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00662             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00663                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z)
00664                     = lattice.get(iX,iY,iZ).computeDensity();
00665             }
00666         }
00667     }
00668 }
00669 
00670 template<typename T, template<typename U> class Descriptor> 
00671 BoxDensityFunctional3D<T,Descriptor>* BoxDensityFunctional3D<T,Descriptor>::clone() const
00672 {
00673     return new BoxDensityFunctional3D<T,Descriptor>(*this);
00674 }
00675 
00676 template<typename T, template<typename U> class Descriptor> 
00677 void BoxDensityFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00678     modified[0] = modif::nothing;
00679     modified[1] = modif::staticVariables;
00680 }
00681 
00682 template<typename T, template<typename U> class Descriptor> 
00683 BlockDomain::DomainT BoxDensityFunctional3D<T,Descriptor>::appliesTo() const {
00684     return BlockDomain::bulkAndEnvelope;
00685 }
00686 
00687 
00688 template<typename T, template<typename U> class Descriptor> 
00689 void BoxRhoBarFunctional3D<T,Descriptor>::process (
00690         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
00691 {
00692     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
00693     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00694        for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00695             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00696                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
00697                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z)
00698                     = cell.getDynamics().computeRhoBar(cell);
00699             }
00700         }
00701     }
00702 }
00703 
00704 template<typename T, template<typename U> class Descriptor> 
00705 BoxRhoBarFunctional3D<T,Descriptor>* BoxRhoBarFunctional3D<T,Descriptor>::clone() const
00706 {
00707     return new BoxRhoBarFunctional3D<T,Descriptor>(*this);
00708 }
00709 
00710 template<typename T, template<typename U> class Descriptor> 
00711 void BoxRhoBarFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00712     modified[0] = modif::nothing;
00713     modified[1] = modif::staticVariables;
00714 }
00715 
00716 template<typename T, template<typename U> class Descriptor> 
00717 BlockDomain::DomainT BoxRhoBarFunctional3D<T,Descriptor>::appliesTo() const {
00718     return BlockDomain::bulkAndEnvelope;
00719 }
00720 
00721 
00722 template<typename T, template<typename U> class Descriptor> 
00723 void BoxRhoBarJfunctional3D<T,Descriptor>::processGenericBlocks (
00724         Box3D domain, std::vector<AtomicBlock3D*> fields )
00725 {
00726     BlockLattice3D<T,Descriptor>& lattice = *dynamic_cast<BlockLattice3D<T,Descriptor>*>(fields[0]);
00727     ScalarField3D<T>& rhoBarField = *dynamic_cast<ScalarField3D<T>*>(fields[1]);
00728     TensorField3D<T,3>& jField = *dynamic_cast<TensorField3D<T,3>*>(fields[2]);
00729     Dot3D offset1 = computeRelativeDisplacement(lattice, rhoBarField);
00730     Dot3D offset2 = computeRelativeDisplacement(lattice, jField);
00731     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00732        for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00733             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00734                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
00735                 momentTemplates<T,Descriptor>::get_rhoBar_j (
00736                         cell,
00737                         rhoBarField.get(iX+offset1.x,iY+offset1.y,iZ+offset1.z),
00738                         jField.get(iX+offset2.x,iY+offset2.y,iZ+offset2.z) );
00739             }
00740         }
00741     }
00742 }
00743 
00744 template<typename T, template<typename U> class Descriptor> 
00745 BoxRhoBarJfunctional3D<T,Descriptor>* BoxRhoBarJfunctional3D<T,Descriptor>::clone() const
00746 {
00747     return new BoxRhoBarJfunctional3D<T,Descriptor>(*this);
00748 }
00749 
00750 template<typename T, template<typename U> class Descriptor> 
00751 void BoxRhoBarJfunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00752     modified[0] = modif::nothing;  // lattice
00753     modified[1] = modif::staticVariables;   // rhoBar
00754     modified[2] = modif::staticVariables;   // j
00755 }
00756 
00757 template<typename T, template<typename U> class Descriptor> 
00758 void PackedRhoBarJfunctional3D<T,Descriptor>::process (
00759         Box3D domain, BlockLattice3D<T,Descriptor>& lattice,
00760                       NTensorField3D<T>& rhoBarJField )
00761 {
00762     Dot3D offset = computeRelativeDisplacement(lattice, rhoBarJField);
00763     T rhoBar;
00764     Array<T,3> j;
00765     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00766        for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00767             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00768                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
00769                 momentTemplates<T,Descriptor>::get_rhoBar_j(cell, rhoBar, j);
00770                 T* rhoBarJ = rhoBarJField.get(iX+offset.x,iY+offset.y,iZ+offset.z);
00771                 *rhoBarJ = rhoBar;
00772                 j.to_cArray(rhoBarJ+1);
00773             }
00774         }
00775     }
00776 }
00777 
00778 template<typename T, template<typename U> class Descriptor> 
00779 PackedRhoBarJfunctional3D<T,Descriptor>* PackedRhoBarJfunctional3D<T,Descriptor>::clone() const
00780 {
00781     return new PackedRhoBarJfunctional3D<T,Descriptor>(*this);
00782 }
00783 
00784 template<typename T, template<typename U> class Descriptor> 
00785 void PackedRhoBarJfunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00786     modified[0] = modif::nothing;  // lattice
00787     modified[1] = modif::staticVariables;   // rhoBarJ
00788 }
00789 
00790 
00791 template<typename T, template<typename U> class Descriptor> 
00792 void BoxKineticEnergyFunctional3D<T,Descriptor>::process (
00793         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
00794 {
00795     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
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                 Array<T,Descriptor<T>::d> velocity;
00800                 lattice.get(iX,iY,iZ).computeVelocity(velocity);
00801                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z)
00802                     = VectorTemplate<T,Descriptor>::normSqr(velocity) / (T)2;
00803             }
00804         }
00805     }
00806 }
00807 
00808 template<typename T, template<typename U> class Descriptor> 
00809 BoxKineticEnergyFunctional3D<T,Descriptor>* BoxKineticEnergyFunctional3D<T,Descriptor>::clone() const
00810 {
00811     return new BoxKineticEnergyFunctional3D<T,Descriptor>(*this);
00812 }
00813 
00814 template<typename T, template<typename U> class Descriptor> 
00815 void BoxKineticEnergyFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00816     modified[0] = modif::nothing;
00817     modified[1] = modif::staticVariables;
00818 }
00819 
00820 template<typename T, template<typename U> class Descriptor> 
00821 BlockDomain::DomainT BoxKineticEnergyFunctional3D<T,Descriptor>::appliesTo() const {
00822     return BlockDomain::bulkAndEnvelope;
00823 }
00824 
00825 
00826 
00827 template<typename T, template<typename U> class Descriptor> 
00828 void BoxVelocityNormFunctional3D<T,Descriptor>::process (
00829         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
00830 {
00831     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
00832     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00833         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00834             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00835                 Array<T,Descriptor<T>::d> velocity;
00836                 lattice.get(iX,iY,iZ).computeVelocity(velocity);
00837                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z)
00838                     = sqrt( VectorTemplate<T,Descriptor>::normSqr(velocity) );
00839             }
00840         }
00841     }
00842 }
00843 
00844 template<typename T, template<typename U> class Descriptor> 
00845 BoxVelocityNormFunctional3D<T,Descriptor>* BoxVelocityNormFunctional3D<T,Descriptor>::clone() const
00846 {
00847     return new BoxVelocityNormFunctional3D<T,Descriptor>(*this);
00848 }
00849 
00850 template<typename T, template<typename U> class Descriptor> 
00851 void BoxVelocityNormFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00852     modified[0] = modif::nothing;
00853     modified[1] = modif::staticVariables;
00854 }
00855 
00856 template<typename T, template<typename U> class Descriptor> 
00857 BlockDomain::DomainT BoxVelocityNormFunctional3D<T,Descriptor>::appliesTo() const {
00858     return BlockDomain::bulkAndEnvelope;
00859 }
00860 
00861 template<typename T, template<typename U> class Descriptor> 
00862 BoxVelocityComponentFunctional3D<T,Descriptor>::BoxVelocityComponentFunctional3D(int iComponent_)
00863     : iComponent(iComponent_)
00864 { }
00865 
00866 template<typename T, template<typename U> class Descriptor> 
00867 void BoxVelocityComponentFunctional3D<T,Descriptor>::process (
00868         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
00869 {
00870     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
00871     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00872         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00873             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00874                 Array<T,Descriptor<T>::d> velocity;
00875                 lattice.get(iX,iY,iZ).computeVelocity(velocity);
00876                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z) = velocity[iComponent];
00877             }
00878         }
00879     }
00880 }
00881 
00882 template<typename T, template<typename U> class Descriptor> 
00883 BoxVelocityComponentFunctional3D<T,Descriptor>* BoxVelocityComponentFunctional3D<T,Descriptor>::clone() const
00884 {
00885     return new BoxVelocityComponentFunctional3D<T,Descriptor>(*this);
00886 }
00887 
00888 template<typename T, template<typename U> class Descriptor> 
00889 void BoxVelocityComponentFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00890     modified[0] = modif::nothing;
00891     modified[1] = modif::staticVariables;
00892 }
00893 
00894 template<typename T, template<typename U> class Descriptor> 
00895 BlockDomain::DomainT BoxVelocityComponentFunctional3D<T,Descriptor>::appliesTo() const {
00896     return BlockDomain::bulkAndEnvelope;
00897 }
00898 
00899 
00900 template<typename T, template<typename U> class Descriptor> 
00901 void BoxVelocityFunctional3D<T,Descriptor>::process (
00902         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, TensorField3D<T,Descriptor<T>::d>& tensorField)
00903 {
00904     Dot3D offset = computeRelativeDisplacement(lattice, tensorField);
00905     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00906         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00907             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00908                 lattice.get(iX,iY,iZ).computeVelocity (
00909                         tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z) );
00910             }
00911         }
00912     }
00913 }
00914 
00915 template<typename T, template<typename U> class Descriptor> 
00916 BoxVelocityFunctional3D<T,Descriptor>* BoxVelocityFunctional3D<T,Descriptor>::clone() const
00917 {
00918     return new BoxVelocityFunctional3D<T,Descriptor>(*this);
00919 }
00920 
00921 template<typename T, template<typename U> class Descriptor> 
00922 void BoxVelocityFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00923     modified[0] = modif::nothing;
00924     modified[1] = modif::staticVariables;
00925 }
00926 
00927 
00928 template<typename T, template<typename U> class Descriptor> 
00929 BlockDomain::DomainT BoxVelocityFunctional3D<T,Descriptor>::appliesTo() const {
00930     return BlockDomain::bulkAndEnvelope;
00931 }
00932 
00933 
00934 template<typename T, template<typename U> class Descriptor> 
00935 void BoxTemperatureFunctional3D<T,Descriptor>::process (
00936         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
00937 {
00938     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
00939     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00940         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00941             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00942                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z)
00943                     = lattice.get(iX,iY,iZ).computeTemperature();
00944             }
00945         }
00946     }
00947 }
00948 
00949 template<typename T, template<typename U> class Descriptor> 
00950 BoxTemperatureFunctional3D<T,Descriptor>* BoxTemperatureFunctional3D<T,Descriptor>::clone() const
00951 {
00952     return new BoxTemperatureFunctional3D<T,Descriptor>(*this);
00953 }
00954 
00955 template<typename T, template<typename U> class Descriptor> 
00956 void BoxTemperatureFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00957     modified[0] = modif::nothing;
00958     modified[1] = modif::staticVariables;
00959 }
00960 
00961 template<typename T, template<typename U> class Descriptor> 
00962 BlockDomain::DomainT BoxTemperatureFunctional3D<T,Descriptor>::appliesTo() const {
00963     return BlockDomain::bulkAndEnvelope;
00964 }
00965 
00966 
00967 template<typename T, template<typename U> class Descriptor> 
00968 void BoxDeviatoricStressFunctional3D<T,Descriptor>::process (
00969         Box3D domain, BlockLattice3D<T,Descriptor>& lattice,
00970         TensorField3D<T,SymmetricTensor<T,Descriptor>::n>& PiNeq )
00971 {
00972     Dot3D offset = computeRelativeDisplacement(lattice, PiNeq);
00973     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00974         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00975             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00976                 lattice.get(iX,iY,iZ).computeDeviatoricStress (
00977                         PiNeq.get(iX+offset.x,iY+offset.y,iZ+offset.z) );
00978             }
00979         }
00980     }
00981 }
00982 
00983 template<typename T, template<typename U> class Descriptor> 
00984 BoxDeviatoricStressFunctional3D<T,Descriptor>* BoxDeviatoricStressFunctional3D<T,Descriptor>::clone() const
00985 {
00986     return new BoxDeviatoricStressFunctional3D<T,Descriptor>(*this);
00987 }
00988 
00989 template<typename T, template<typename U> class Descriptor> 
00990 void BoxDeviatoricStressFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00991     modified[0] = modif::nothing;
00992     modified[1] = modif::staticVariables;
00993 }
00994 
00995 template<typename T, template<typename U> class Descriptor> 
00996 BlockDomain::DomainT BoxDeviatoricStressFunctional3D<T,Descriptor>::appliesTo() const {
00997     return BlockDomain::bulkAndEnvelope;
00998 }
00999 
01000 
01001 template<typename T, template<typename U> class Descriptor> 
01002 void BoxStrainRateFromStressFunctional3D<T,Descriptor>::process (
01003         Box3D domain, BlockLattice3D<T,Descriptor>& lattice,
01004         TensorField3D<T,SymmetricTensor<T,Descriptor>::n>& S )
01005 {
01006     Dot3D offset = computeRelativeDisplacement(lattice, S);
01007     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01008         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01009             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01010                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
01011                 Array<T,SymmetricTensor<T,Descriptor>::n>& element
01012                     = S.get(iX+offset.x,iY+offset.y,iZ+offset.z);
01013                 cell.computeDeviatoricStress(element);
01014                 T omega     = cell.getDynamics().getOmega();
01015                 T rhoBar    = cell.getDynamics().computeRhoBar(cell);
01016                 T prefactor = - omega * Descriptor<T>::invCs2 *
01017                                 Descriptor<T>::invRho(rhoBar) / (T)2;
01018                 for (int iTensor=0; iTensor<SymmetricTensor<T,Descriptor>::n; ++iTensor) {
01019                     element[iTensor] *= prefactor;
01020                 }
01021             }
01022         }
01023     }
01024 }
01025 
01026 template<typename T, template<typename U> class Descriptor> 
01027 BoxStrainRateFromStressFunctional3D<T,Descriptor>* BoxStrainRateFromStressFunctional3D<T,Descriptor>::clone() const
01028 {
01029     return new BoxStrainRateFromStressFunctional3D<T,Descriptor>(*this);
01030 }
01031 
01032 template<typename T, template<typename U> class Descriptor> 
01033 void BoxStrainRateFromStressFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01034     modified[0] = modif::nothing;
01035     modified[1] = modif::staticVariables;
01036 }
01037 
01038 template<typename T, template<typename U> class Descriptor> 
01039 BlockDomain::DomainT BoxStrainRateFromStressFunctional3D<T,Descriptor>::appliesTo() const {
01040     return BlockDomain::bulkAndEnvelope;
01041 }
01042 
01043 template<typename T>
01044 void BoxQcriterionFunctional3D<T>::processGenericBlocks(Box3D domain, std::vector<AtomicBlock3D*> fields) {
01045     TensorField3D<T,3>& vorticity = *dynamic_cast<TensorField3D<T,3>*>(fields[0]);
01046     TensorField3D<T,6>& strain = *dynamic_cast<TensorField3D<T,6>*>(fields[1]);
01047     ScalarField3D<T>& qCriterion = *dynamic_cast<ScalarField3D<T>*>(fields[2]);
01048     Dot3D offset1 = computeRelativeDisplacement(vorticity, strain);
01049     Dot3D offset2 = computeRelativeDisplacement(vorticity, qCriterion);
01050     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01051         plint oX1 = iX + offset1.x;
01052         plint oX2 = iX + offset2.x;
01053         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01054             plint oY1 = iY + offset1.y;
01055             plint oY2 = iY + offset2.y;
01056             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01057                 plint oZ1 = iZ + offset1.z;
01058                 plint oZ2 = iZ + offset2.z;
01059                 
01060                 T vortNorm = VectorTemplateImpl<T,3>::normSqr(vorticity.get(iX,iY,iZ));
01061                 T normStrain = SymmetricTensorImpl<T,3>::tensorNormSqr(strain.get(oX1,oY1,oZ1));
01062                 
01063                 qCriterion.get(oX2,oY2,oZ2) = (vortNorm-(T)2*normStrain)/(T)4;
01064             }
01065         }
01066     }
01067 }
01068 
01069 template<typename T>
01070 BoxQcriterionFunctional3D<T>* BoxQcriterionFunctional3D<T>::clone() const {
01071     return new BoxQcriterionFunctional3D<T>(*this);
01072 }
01073 
01074 template<typename T>
01075 void BoxQcriterionFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01076     modified[0] = modif::nothing;
01077     modified[1] = modif::nothing;
01078     modified[2] = modif::staticVariables;
01079 }
01080 
01081 template<typename T>
01082 BlockDomain::DomainT BoxQcriterionFunctional3D<T>::appliesTo() const {
01083     return BlockDomain::bulkAndEnvelope;
01084 }
01085 
01086 
01087 template<typename T, template<typename U> class Descriptor> 
01088 BoxPopulationFunctional3D<T,Descriptor>::BoxPopulationFunctional3D(plint iComponent_)
01089     : iComponent(iComponent_)
01090 { }
01091 
01092 template<typename T, template<typename U> class Descriptor> 
01093 void BoxPopulationFunctional3D<T,Descriptor>::process (
01094         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
01095 {
01096     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
01097     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01098         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01099             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01100                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z) = lattice.get(iX,iY,iZ)[iComponent];
01101             }
01102         }
01103     }
01104 }
01105 
01106 template<typename T, template<typename U> class Descriptor> 
01107 BoxPopulationFunctional3D<T,Descriptor>* BoxPopulationFunctional3D<T,Descriptor>::clone() const
01108 {
01109     return new BoxPopulationFunctional3D<T,Descriptor>(*this);
01110 }
01111 
01112 template<typename T, template<typename U> class Descriptor> 
01113 void BoxPopulationFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01114     modified[0] = modif::nothing;
01115     modified[1] = modif::staticVariables;
01116 }
01117 
01118 template<typename T, template<typename U> class Descriptor> 
01119 BlockDomain::DomainT BoxPopulationFunctional3D<T,Descriptor>::appliesTo() const {
01120     return BlockDomain::bulkAndEnvelope;
01121 }
01122 
01123 
01124 template<typename T, template<typename U> class Descriptor> 
01125 BoxEquilibriumFunctional3D<T,Descriptor>::BoxEquilibriumFunctional3D(plint iComponent_)
01126     : iComponent(iComponent_)
01127 { }
01128 
01129 template<typename T, template<typename U> class Descriptor> 
01130 void BoxEquilibriumFunctional3D<T,Descriptor>::process (
01131         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& equilibrium)
01132 {
01133     Dot3D offset = computeRelativeDisplacement(lattice, equilibrium);
01134     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01135         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01136             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01137                 T rhoBar;
01138                 Array<T,Descriptor<T>::d> j;
01139                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
01140                 cell.getDynamics().computeRhoBarJ(cell, rhoBar, j);
01141                 T jSqr = normSqr(j);
01142                 equilibrium.get(iX+offset.x,iY+offset.y,iZ+offset.z) =
01143                     cell.computeEquilibrium(iComponent, rhoBar, j, jSqr);
01144             }
01145         }
01146     }
01147 }
01148 
01149 template<typename T, template<typename U> class Descriptor> 
01150 BoxEquilibriumFunctional3D<T,Descriptor>* BoxEquilibriumFunctional3D<T,Descriptor>::clone() const
01151 {
01152     return new BoxEquilibriumFunctional3D<T,Descriptor>(*this);
01153 }
01154 
01155 template<typename T, template<typename U> class Descriptor> 
01156 void BoxEquilibriumFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01157     modified[0] = modif::nothing;
01158     modified[1] = modif::staticVariables;
01159 }
01160 
01161 template<typename T, template<typename U> class Descriptor> 
01162 BlockDomain::DomainT BoxEquilibriumFunctional3D<T,Descriptor>::appliesTo() const {
01163     return BlockDomain::bulkAndEnvelope;
01164 }
01165 
01166 
01167 template<typename T, template<typename U> class Descriptor> 
01168 BoxAllPopulationsFunctional3D<T,Descriptor>::BoxAllPopulationsFunctional3D()
01169 { }
01170 
01171 template<typename T, template<typename U> class Descriptor> 
01172 void BoxAllPopulationsFunctional3D<T,Descriptor>::process (
01173         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, TensorField3D<T,Descriptor<T>::q>& tensorField)
01174 {
01175     Dot3D offset = computeRelativeDisplacement(lattice, tensorField);
01176     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01177         plint oX = iX+offset.x;
01178         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01179             plint oY = iY+offset.y;
01180             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01181                 for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop) {
01182                     tensorField.get(oX,oY,iZ+offset.z)[iPop] = lattice.get(iX,iY,iZ)[iPop];
01183                 }
01184             }
01185         }
01186     }
01187 }
01188 
01189 template<typename T, template<typename U> class Descriptor> 
01190 BoxAllPopulationsFunctional3D<T,Descriptor>* BoxAllPopulationsFunctional3D<T,Descriptor>::clone() const
01191 {
01192     return new BoxAllPopulationsFunctional3D<T,Descriptor>(*this);
01193 }
01194 
01195 template<typename T, template<typename U> class Descriptor> 
01196 void BoxAllPopulationsFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01197     modified[0] = modif::nothing;
01198     modified[1] = modif::staticVariables;
01199 }
01200 
01201 template<typename T, template<typename U> class Descriptor> 
01202 BlockDomain::DomainT BoxAllPopulationsFunctional3D<T,Descriptor>::appliesTo() const {
01203     return BlockDomain::bulkAndEnvelope;
01204 }
01205 
01206 template<typename T, template<typename U> class Descriptor> 
01207 BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>::BoxAllPopulationsToLatticeFunctional3D()
01208 { }
01209 
01210 template<typename T, template<typename U> class Descriptor> 
01211 void BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>::process (
01212         Box3D domain, BlockLattice3D<T,Descriptor>& lattice, TensorField3D<T,Descriptor<T>::q>& tensorField)
01213 {
01214     Dot3D offset = computeRelativeDisplacement(lattice, tensorField);
01215     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01216         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01217             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01218                 for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop) {
01219                     lattice.get(iX,iY,iZ)[iPop] = tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z)[iPop];
01220                 }
01221             }
01222         }
01223     }
01224 }
01225 
01226 template<typename T, template<typename U> class Descriptor> 
01227 BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>* BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>::clone() const
01228 {
01229     return new BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>(*this);
01230 }
01231 
01232 template<typename T, template<typename U> class Descriptor> 
01233 void BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01234     modified[0] = modif::staticVariables;
01235     modified[1] = modif::nothing;
01236 }
01237 
01238 template<typename T, template<typename U> class Descriptor> 
01239 BlockDomain::DomainT BoxAllPopulationsToLatticeFunctional3D<T,Descriptor>::appliesTo() const {
01240     return BlockDomain::bulkAndEnvelope;
01241 }
01242 
01243 template<typename T, template<typename U> class Descriptor> 
01244 void BoxOmegaFunctional3D<T,Descriptor>::process (
01245     Box3D domain, BlockLattice3D<T,Descriptor>& lattice, ScalarField3D<T>& scalarField)
01246 {
01247     Dot3D offset = computeRelativeDisplacement(lattice, scalarField);
01248     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01249         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01250             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01251                 Cell<T,Descriptor> const& cell = lattice.get(iX,iY,iZ);
01252                 scalarField.get(iX+offset.x,iY+offset.y,iZ+offset.z) = cell.getDynamics().getOmega();
01253             }
01254         }
01255     }
01256 }
01257 
01258 template<typename T, template<typename U> class Descriptor> 
01259 BoxOmegaFunctional3D<T,Descriptor>* BoxOmegaFunctional3D<T,Descriptor>::clone() const
01260 {
01261     return new BoxOmegaFunctional3D<T,Descriptor>(*this);
01262 }
01263 
01264 template<typename T, template<typename U> class Descriptor> 
01265 void BoxOmegaFunctional3D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01266     modified[0] = modif::nothing;
01267     modified[1] = modif::staticVariables;
01268 }
01269 
01270 template<typename T, template<typename U> class Descriptor> 
01271 BlockDomain::DomainT BoxOmegaFunctional3D<T,Descriptor>::appliesTo() const {
01272     return BlockDomain::bulkAndEnvelope;
01273 }
01274 
01275 /* *************** PART II ******************************************* */
01276 /* *************** Analysis of the scalar-field ********************** */
01277 /* ******************************************************************* */
01278 
01279 /* *************** Reductive Data Functionals for scalar-field ******* */
01280 
01281 template<typename T>
01282 BoxScalarSumFunctional3D<T>::BoxScalarSumFunctional3D()
01283     : sumScalarId(this->getStatistics().subscribeSum())
01284 { }
01285 
01286 template<typename T>
01287 void BoxScalarSumFunctional3D<T>::process (
01288         Box3D domain, ScalarField3D<T>& scalarField )
01289 {
01290     BlockStatistics& statistics = this->getStatistics();
01291     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01292         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01293             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01294                 statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY,iZ));
01295             }
01296         }
01297     }
01298 }
01299 
01300 template<typename T>
01301 BoxScalarSumFunctional3D<T>* BoxScalarSumFunctional3D<T>::clone() const
01302 {
01303     return new BoxScalarSumFunctional3D<T>(*this);
01304 }
01305 
01306 template<typename T>
01307 T BoxScalarSumFunctional3D<T>::getSumScalar() const {
01308     double doubleSum = this->getStatistics().getSum(sumScalarId);
01309     // The sum is internally computed on floating-point values. If T is
01310     //   integer, the value must be rounded at the end.
01311     if (std::numeric_limits<T>::is_integer) {
01312         return (T) util::roundToInt(doubleSum);
01313     }
01314     return (T) doubleSum;
01315 }
01316 
01317 
01318 template<typename T>
01319 MaskedBoxScalarAverageFunctional3D<T>::MaskedBoxScalarAverageFunctional3D(int flag_)
01320     : averageScalarId(this->getStatistics().subscribeAverage()),
01321       flag(flag_)
01322 { }
01323 
01324 template<typename T>
01325 void MaskedBoxScalarAverageFunctional3D<T>::process (
01326         Box3D domain,
01327         ScalarField3D<T>& scalarField,
01328         ScalarField3D<int>& mask )
01329 {
01330     Dot3D offset = computeRelativeDisplacement(scalarField, mask);
01331     BlockStatistics& statistics = this->getStatistics();
01332     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01333         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01334             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01335                 if (mask.get(iX+offset.x, iY+offset.y, iZ+offset.z)==flag) {
01336                     statistics.gatherAverage(averageScalarId, (double)scalarField.get(iX,iY,iZ));
01337                     statistics.incrementStats();
01338                 }
01339             }
01340         }
01341     }
01342 }
01343 
01344 template<typename T>
01345 MaskedBoxScalarAverageFunctional3D<T>* MaskedBoxScalarAverageFunctional3D<T>::clone() const
01346 {
01347     return new MaskedBoxScalarAverageFunctional3D<T>(*this);
01348 }
01349 
01350 template<typename T>
01351 T MaskedBoxScalarAverageFunctional3D<T>::getAverageScalar() const {
01352     double doubleAverage = this->getStatistics().getAverage(averageScalarId);
01353     // The average is internally computed on floating-point values. If T is
01354     //   integer, the value must be rounded at the end.
01355     if (std::numeric_limits<T>::is_integer) {
01356         return (T) util::roundToInt(doubleAverage);
01357     }
01358     return (T) doubleAverage;
01359 }
01360 
01361 
01362 template<typename T>
01363 BoxScalarMinFunctional3D<T>::BoxScalarMinFunctional3D()
01364     : maxScalarId(this->getStatistics().subscribeMax())
01365 { }
01366 
01367 template<typename T>
01368 void BoxScalarMinFunctional3D<T>::process (
01369         Box3D domain, ScalarField3D<T>& scalarField )
01370 {
01371     BlockStatistics& statistics = this->getStatistics();
01372     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01373         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01374             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01375                 // BlockStatistics computes only maximum, no minimum. Therefore,
01376                 //   the relation min(x) = -max(-x) is used.
01377                 statistics.gatherMax(maxScalarId, -(double)scalarField.get(iX,iY,iZ));
01378             }
01379         }
01380     }
01381 }
01382 
01383 template<typename T>
01384 BoxScalarMinFunctional3D<T>* BoxScalarMinFunctional3D<T>::clone() const
01385 {
01386     return new BoxScalarMinFunctional3D<T>(*this);
01387 }
01388 
01389 template<typename T>
01390 T BoxScalarMinFunctional3D<T>::getMinScalar() const {
01391     // The minus sign accounts for the relation min(x) = -max(-x).
01392     // The sum is internally computed on floating-point values. If T is
01393     //   integer, the value must be rounded at the end.
01394     double doubleMin = - this->getStatistics().getMax(maxScalarId);
01395     if (std::numeric_limits<T>::is_integer) {
01396         return (T) util::roundToInt(doubleMin);
01397     }
01398     return (T) doubleMin;
01399 }
01400 
01401 
01402 template<typename T>
01403 BoxScalarMaxFunctional3D<T>::BoxScalarMaxFunctional3D()
01404     : maxScalarId(this->getStatistics().subscribeMax())
01405 { }
01406 
01407 template<typename T>
01408 void BoxScalarMaxFunctional3D<T>::process (
01409         Box3D domain, ScalarField3D<T>& scalarField )
01410 {
01411     BlockStatistics& statistics = this->getStatistics();
01412     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01413         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01414             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01415                 statistics.gatherMax(maxScalarId, (double)scalarField.get(iX,iY,iZ));
01416             }
01417         }
01418     }
01419 }
01420 
01421 template<typename T>
01422 BoxScalarMaxFunctional3D<T>* BoxScalarMaxFunctional3D<T>::clone() const
01423 {
01424     return new BoxScalarMaxFunctional3D<T>(*this);
01425 }
01426 
01427 template<typename T>
01428 T BoxScalarMaxFunctional3D<T>::getMaxScalar() const {
01429     // The sum is internally computed on floating-point values. If T is
01430     //   integer, the value must be rounded at the end.
01431     double doubleMax = this->getStatistics().getMax(maxScalarId);
01432     if (std::numeric_limits<T>::is_integer) {
01433         return (T) util::roundToInt(doubleMax);
01434     }
01435     return (T) doubleMax;
01436 }
01437 
01438 
01439 template<typename T>
01440 BoundedBoxScalarSumFunctional3D<T>::BoundedBoxScalarSumFunctional3D()
01441     : sumScalarId(this->getStatistics().subscribeSum())
01442 { }
01443 
01444 template<typename T>
01445 void BoundedBoxScalarSumFunctional3D<T>::processBulk (
01446         Box3D domain, ScalarField3D<T>& scalarField )
01447 {
01448     BlockStatistics& statistics = this->getStatistics();
01449     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01450         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01451             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01452                 statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY,iZ));
01453             }
01454         }
01455     }
01456 }
01457 
01458 template<typename T>
01459 void BoundedBoxScalarSumFunctional3D<T>::processPlane (
01460         int direction, int orientation,
01461         Box3D domain, ScalarField3D<T>& scalarField )
01462 {
01463     BlockStatistics& statistics = this->getStatistics();
01464     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01465         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01466             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01467                 // Plane boundary nodes have a weight of 0.5, because only 50% of the
01468                 //   cell centered at the node is inside the computational domain.
01469                 statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY,iZ) / 2.);
01470             }
01471         }
01472     }
01473 }
01474 
01475 template<typename T>
01476 void BoundedBoxScalarSumFunctional3D<T>::processEdge (
01477         int plane, int normal1, int normal2,
01478         Box3D domain, ScalarField3D<T>& scalarField )
01479 {
01480     BlockStatistics& statistics = this->getStatistics();
01481     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01482         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01483             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01484                 // Edge nodes have a weight of 0.25, because only 25% of the
01485                 //   cell centered at the node is inside the computational domain.
01486                 statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY,iZ) / 4.);
01487             }
01488         }
01489     }
01490 }
01491 
01492 template<typename T>
01493 void BoundedBoxScalarSumFunctional3D<T>::processCorner (
01494         int normalX, int normalY, int normalZ,
01495         Box3D domain, ScalarField3D<T>& scalarField )
01496 {
01497     BlockStatistics& statistics = this->getStatistics();
01498     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01499         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01500             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01501                 // Corner nodes have a weight of 0.125, because only 1/8 of the
01502                 //   cell centered at the node is inside the computational domain.
01503                 statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY,iZ) / 8.);
01504             }
01505         }
01506     }
01507 }
01508 
01509 template<typename T>
01510 BoundedBoxScalarSumFunctional3D<T>* BoundedBoxScalarSumFunctional3D<T>::clone() const
01511 {
01512     return new BoundedBoxScalarSumFunctional3D<T>(*this);
01513 }
01514 
01515 template<typename T>
01516 T BoundedBoxScalarSumFunctional3D<T>::getSumScalar() const {
01517     double doubleSum = this->getStatistics().getSum(sumScalarId);
01518     // The sum is internally computed on floating-point values. If T is
01519     //   integer, the value must be rounded at the end.
01520     if (std::numeric_limits<T>::is_integer) {
01521         return (T) util::roundToInt(doubleSum);
01522     }
01523     return (T) doubleSum;
01524 }
01525 
01526 template<typename T1, typename T2>
01527 void CopyConvertScalarFunctional3D<T1,T2>::process (
01528             Box3D domain, ScalarField3D<T1>& field1,
01529                       ScalarField3D<T2>& field2 )
01530 {
01531     Dot3D offset = computeRelativeDisplacement(field1, field2);
01532 
01533     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01534         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01535             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01536                 field2.get(iX+offset.x,iY+offset.y,iZ+offset.z) =
01537                     (T2) field1.get(iX,iY,iZ);
01538             }
01539         }
01540     }
01541 }
01542 
01543 template<typename T1, typename T2>
01544 CopyConvertScalarFunctional3D<T1,T2>* CopyConvertScalarFunctional3D<T1,T2>::clone() const
01545 {
01546     return new CopyConvertScalarFunctional3D<T1,T2>(*this);
01547 }
01548 
01549 template<typename T1, typename T2>
01550 void CopyConvertScalarFunctional3D<T1,T2>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01551     modified[0] = modif::nothing;
01552     modified[1] = modif::staticVariables;
01553 }
01554 
01555 template<typename T1, typename T2>
01556 BlockDomain::DomainT CopyConvertScalarFunctional3D<T1,T2>::appliesTo() const {
01557     return BlockDomain::bulk;
01558 }
01559 
01560 
01561 
01562 /* *************** Data Functionals for scalar-fields **************** */
01563 
01564 template<typename T>
01565 void ExtractScalarSubDomainFunctional3D<T>::process (
01566         Box3D domain, ScalarField3D<T>& field1,
01567                       ScalarField3D<T>& field2 )
01568 {
01569     Dot3D offset = computeRelativeDisplacement(field1, field2);
01570     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01571         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01572             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01573                 field2.get(iX+offset.x,iY+offset.y,iZ+offset.z) = field1.get(iX,iY,iZ);
01574             }
01575         }
01576     }
01577 }
01578 
01579 template<typename T>
01580 ExtractScalarSubDomainFunctional3D<T>* ExtractScalarSubDomainFunctional3D<T>::clone() const
01581 {
01582     return new ExtractScalarSubDomainFunctional3D<T>(*this);
01583 }
01584 
01585 template<typename T>
01586 void ExtractScalarSubDomainFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01587     modified[0] = modif::nothing;
01588     modified[1] = modif::staticVariables;
01589 }
01590 
01591 template<typename T>
01592 BlockDomain::DomainT ExtractScalarSubDomainFunctional3D<T>::appliesTo() const {
01593     return BlockDomain::bulkAndEnvelope;
01594 }
01595 
01596 /* ******** compute sqrt functional 3D ************************************* */
01597 
01598 template<typename T>
01599 void ComputeScalarSqrtFunctional3D<T>::process (
01600         Box3D domain, ScalarField3D<T>& A,
01601                       ScalarField3D<T>& B )
01602 {
01603     Dot3D offset = computeRelativeDisplacement(A, B);
01604     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01605         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01606             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01607                 PLB_ASSERT( A.get(iX,iY,iZ) >= T());
01608                 B.get(iX+offset.x,iY+offset.y,iZ+offset.z) = std::sqrt( A.get(iX,iY,iZ) );
01609             }
01610         }
01611     }
01612 }
01613 
01614 template<typename T>
01615 ComputeScalarSqrtFunctional3D<T>* ComputeScalarSqrtFunctional3D<T>::clone() const
01616 {
01617     return new ComputeScalarSqrtFunctional3D<T>(*this);
01618 }
01619 
01620 template<typename T>
01621 void ComputeScalarSqrtFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01622     modified[0] = modif::nothing;
01623     modified[1] = modif::staticVariables;
01624 }
01625 
01626 template<typename T>
01627 BlockDomain::DomainT ComputeScalarSqrtFunctional3D<T>::appliesTo() const {
01628     return BlockDomain::bulkAndEnvelope;
01629 }
01630 
01631 
01632 /* ******** compute sqrt functional 3D ************************************* */
01633 
01634 template<typename T>
01635 void ComputeAbsoluteValueFunctional3D<T>::process (
01636         Box3D domain, ScalarField3D<T>& A,
01637                       ScalarField3D<T>& B )
01638 {
01639     Dot3D offset = computeRelativeDisplacement(A, B);
01640     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01641         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01642             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01643                 B.get(iX+offset.x,iY+offset.y,iZ+offset.z) = fabs( A.get(iX,iY,iZ) );
01644             }
01645         }
01646     }
01647 }
01648 
01649 template<typename T>
01650 ComputeAbsoluteValueFunctional3D<T>* ComputeAbsoluteValueFunctional3D<T>::clone() const
01651 {
01652     return new ComputeAbsoluteValueFunctional3D<T>(*this);
01653 }
01654 
01655 template<typename T>
01656 void ComputeAbsoluteValueFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01657     modified[0] = modif::nothing;
01658     modified[1] = modif::staticVariables;
01659 }
01660 
01661 template<typename T>
01662 BlockDomain::DomainT ComputeAbsoluteValueFunctional3D<T>::appliesTo() const {
01663     return BlockDomain::bulkAndEnvelope;
01664 }
01665 
01666 /* ******** compute sqrt functional 3D ************************************* */
01667 
01668 template<typename T, int nDim>
01669 void ComputeTensorSqrtFunctional3D<T,nDim>::process (
01670         Box3D domain, TensorField3D<T,nDim>& A,
01671                       TensorField3D<T,nDim>& B )
01672 {
01673     Dot3D offset = computeRelativeDisplacement(A, B);
01674     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01675         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01676             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01677                 for (plint iD = 0; iD < nDim; ++iD) {
01678                     PLB_ASSERT( A.get(iX,iY,iZ)[iD] >= T());
01679                     B.get(iX+offset.x,iY+offset.y,iZ+offset.z)[iD] = std::sqrt( A.get(iX,iY,iZ)[iD] );
01680                 }
01681             }
01682         }
01683     }
01684 }
01685 
01686 template<typename T, int nDim>
01687 ComputeTensorSqrtFunctional3D<T,nDim>* ComputeTensorSqrtFunctional3D<T,nDim>::clone() const
01688 {
01689     return new ComputeTensorSqrtFunctional3D<T,nDim>(*this);
01690 }
01691 
01692 template<typename T, int nDim>
01693 void ComputeTensorSqrtFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01694     modified[0] = modif::nothing;
01695     modified[1] = modif::staticVariables;
01696 }
01697 
01698 template<typename T, int nDim>
01699 BlockDomain::DomainT ComputeTensorSqrtFunctional3D<T,nDim>::appliesTo() const {
01700     return BlockDomain::bulkAndEnvelope;
01701 }
01702 
01703 
01704 /* ******** A_lt_alpha_functional3D ************************************* */
01705 
01706 template<typename T>
01707 A_lt_alpha_functional3D<T>::A_lt_alpha_functional3D(T alpha_)
01708     : alpha(alpha_)
01709 { }
01710 
01711 template<typename T>
01712 void A_lt_alpha_functional3D<T>::process (
01713         Box3D domain, ScalarField3D<T>& A, ScalarField3D<int>& result )
01714 {
01715     Dot3D offset = computeRelativeDisplacement(A, result);
01716     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01717         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01718             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01719                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) =
01720                     A.get(iX,iY,iZ) < alpha ? 1 : 0;
01721             }
01722         }
01723     }
01724 }
01725 
01726 template<typename T>
01727 A_lt_alpha_functional3D<T>* A_lt_alpha_functional3D<T>::clone() const {
01728     return new A_lt_alpha_functional3D<T>(*this);
01729 }
01730 
01731 template<typename T>
01732 void A_lt_alpha_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01733     modified[0] = modif::nothing;
01734     modified[1] = modif::staticVariables;
01735 }
01736 
01737 template<typename T>
01738 BlockDomain::DomainT A_lt_alpha_functional3D<T>::appliesTo() const {
01739     return BlockDomain::bulkAndEnvelope;
01740 }
01741 
01742 
01743 /* ******** A_gt_alpha_functional3D ************************************* */
01744 
01745 template<typename T>
01746 A_gt_alpha_functional3D<T>::A_gt_alpha_functional3D(T alpha_)
01747     : alpha(alpha_)
01748 { }
01749 
01750 template<typename T>
01751 void A_gt_alpha_functional3D<T>::process (
01752         Box3D domain, ScalarField3D<T>& A, ScalarField3D<int>& result )
01753 {
01754     Dot3D offset = computeRelativeDisplacement(A, result);
01755     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01756         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01757             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01758                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) =
01759                     A.get(iX,iY,iZ) > alpha ? 1 : 0;
01760             }
01761         }
01762     }
01763 }
01764 
01765 template<typename T>
01766 A_gt_alpha_functional3D<T>* A_gt_alpha_functional3D<T>::clone() const {
01767     return new A_gt_alpha_functional3D<T>(*this);
01768 }
01769 
01770 template<typename T>
01771 void A_gt_alpha_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01772     modified[0] = modif::nothing;
01773     modified[1] = modif::staticVariables;
01774 }
01775 
01776 template<typename T>
01777 BlockDomain::DomainT A_gt_alpha_functional3D<T>::appliesTo() const {
01778     return BlockDomain::bulkAndEnvelope;
01779 }
01780 
01781 
01782 /* ******** A_plus_alpha_functional3D ************************************* */
01783 
01784 template<typename T>
01785 A_plus_alpha_functional3D<T>::A_plus_alpha_functional3D(T alpha_)
01786     : alpha(alpha_)
01787 { }
01788 
01789 template<typename T>
01790 void A_plus_alpha_functional3D<T>::process (
01791         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& result )
01792 {
01793     Dot3D offset = computeRelativeDisplacement(A, result);
01794     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01795         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01796             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01797                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = A.get(iX,iY,iZ) + alpha;
01798             }
01799         }
01800     }
01801 }
01802 
01803 template<typename T>
01804 A_plus_alpha_functional3D<T>* A_plus_alpha_functional3D<T>::clone() const {
01805     return new A_plus_alpha_functional3D<T>(*this);
01806 }
01807 
01808 template<typename T>
01809 void A_plus_alpha_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01810     modified[0] = modif::nothing;
01811     modified[1] = modif::staticVariables;
01812 }
01813 
01814 template<typename T>
01815 BlockDomain::DomainT A_plus_alpha_functional3D<T>::appliesTo() const {
01816     return BlockDomain::bulkAndEnvelope;
01817 }
01818 
01819 
01820 /* ******** A_minus_alpha_functional3D ************************************** */
01821 
01822 template<typename T>
01823 A_minus_alpha_functional3D<T>::A_minus_alpha_functional3D(T alpha_)
01824     : alpha(alpha_)
01825 { }
01826 
01827 template<typename T>
01828 void A_minus_alpha_functional3D<T>::process (
01829         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& result )
01830 {
01831     Dot3D offset = computeRelativeDisplacement(A, result);
01832     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01833         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01834             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01835                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = A.get(iX,iY,iZ) - alpha;
01836             }
01837         }
01838     }
01839 }
01840 
01841 template<typename T>
01842 A_minus_alpha_functional3D<T>* A_minus_alpha_functional3D<T>::clone() const {
01843     return new A_minus_alpha_functional3D<T>(*this);
01844 }
01845 
01846 template<typename T>
01847 void A_minus_alpha_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01848     modified[0] = modif::nothing;
01849     modified[1] = modif::staticVariables;
01850 }
01851 
01852 template<typename T>
01853 BlockDomain::DomainT A_minus_alpha_functional3D<T>::appliesTo() const {
01854     return BlockDomain::bulkAndEnvelope;
01855 }
01856 
01857 
01858 /* ******** Alpha_minus_A_functional3D ************************************* */
01859 
01860 template<typename T>
01861 Alpha_minus_A_functional3D<T>::Alpha_minus_A_functional3D(T alpha_)
01862     : alpha(alpha_)
01863 { }
01864 
01865 template<typename T>
01866 void Alpha_minus_A_functional3D<T>::process (
01867         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& result )
01868 {
01869     Dot3D offset = computeRelativeDisplacement(A, result);
01870     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01871         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01872             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01873                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = alpha - A.get(iX,iY,iZ);
01874             }
01875         }
01876     }
01877 }
01878 
01879 template<typename T>
01880 Alpha_minus_A_functional3D<T>* Alpha_minus_A_functional3D<T>::clone() const {
01881     return new Alpha_minus_A_functional3D<T>(*this);
01882 }
01883 
01884 template<typename T>
01885 void Alpha_minus_A_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01886     modified[0] = modif::nothing;
01887     modified[1] = modif::staticVariables;
01888 }
01889 
01890 template<typename T>
01891 BlockDomain::DomainT Alpha_minus_A_functional3D<T>::appliesTo() const {
01892     return BlockDomain::bulkAndEnvelope;
01893 }
01894 
01895 
01896 
01897 /* ******** A_times_alpha_functional3D ************************************* */
01898 
01899 template<typename T>
01900 A_times_alpha_functional3D<T>::A_times_alpha_functional3D(T alpha_)
01901     : alpha(alpha_)
01902 { }
01903 
01904 template<typename T>
01905 void A_times_alpha_functional3D<T>::process (
01906         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& result )
01907 {
01908     Dot3D offset = computeRelativeDisplacement(A, result);
01909     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01910         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01911             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01912                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = A.get(iX,iY,iZ) * alpha;
01913             }
01914         }
01915     }
01916 }
01917 
01918 template<typename T>
01919 A_times_alpha_functional3D<T>* A_times_alpha_functional3D<T>::clone() const {
01920     return new A_times_alpha_functional3D<T>(*this);
01921 }
01922 
01923 template<typename T>
01924 void A_times_alpha_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01925     modified[0] = modif::nothing;
01926     modified[1] = modif::staticVariables;
01927 }
01928 
01929 template<typename T>
01930 BlockDomain::DomainT A_times_alpha_functional3D<T>::appliesTo() const {
01931     return BlockDomain::bulkAndEnvelope;
01932 }
01933 
01934 
01935 /* ******** A_dividedBy_alpha_functional3D ************************************* */
01936 
01937 template<typename T>
01938 A_dividedBy_alpha_functional3D<T>::A_dividedBy_alpha_functional3D(T alpha_)
01939     : alpha(alpha_)
01940 { }
01941 
01942 template<typename T>
01943 void A_dividedBy_alpha_functional3D<T>::process (
01944         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& result )
01945 {
01946     Dot3D offset = computeRelativeDisplacement(A, result);
01947     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01948         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01949             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01950                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = A.get(iX,iY,iZ) / alpha;
01951             }
01952         }
01953     }
01954 }
01955 
01956 template<typename T>
01957 A_dividedBy_alpha_functional3D<T>* A_dividedBy_alpha_functional3D<T>::clone() const {
01958     return new A_dividedBy_alpha_functional3D<T>(*this);
01959 }
01960 
01961 template<typename T>
01962 void A_dividedBy_alpha_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01963     modified[0] = modif::nothing;
01964     modified[1] = modif::staticVariables;
01965 }
01966 
01967 template<typename T>
01968 BlockDomain::DomainT A_dividedBy_alpha_functional3D<T>::appliesTo() const {
01969     return BlockDomain::bulkAndEnvelope;
01970 }
01971 
01972 
01973 /* ******** Alpha_dividedBy_A_functional3D ************************************* */
01974 
01975 template<typename T>
01976 Alpha_dividedBy_A_functional3D<T>::Alpha_dividedBy_A_functional3D(T alpha_)
01977     : alpha(alpha_)
01978 { }
01979 
01980 template<typename T>
01981 void Alpha_dividedBy_A_functional3D<T>::process (
01982         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& result )
01983 {
01984     Dot3D offset = computeRelativeDisplacement(A, result);
01985     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01986         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01987             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
01988                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = alpha / A.get(iX,iY,iZ);
01989             }
01990         }
01991     }
01992 }
01993 
01994 template<typename T>
01995 Alpha_dividedBy_A_functional3D<T>* Alpha_dividedBy_A_functional3D<T>::clone() const {
01996     return new Alpha_dividedBy_A_functional3D<T>(*this);
01997 }
01998 
01999 template<typename T>
02000 void Alpha_dividedBy_A_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02001     modified[0] = modif::nothing;
02002     modified[1] = modif::staticVariables;
02003 }
02004 
02005 template<typename T>
02006 BlockDomain::DomainT Alpha_dividedBy_A_functional3D<T>::appliesTo() const {
02007     return BlockDomain::bulkAndEnvelope;
02008 }
02009 
02010 
02011 
02012 /* ******** A_plus_alpha_inplace_functional3D ************************************* */
02013 
02014 template<typename T>
02015 A_plus_alpha_inplace_functional3D<T>::A_plus_alpha_inplace_functional3D(T alpha_)
02016     : alpha(alpha_)
02017 { }
02018 
02019 template<typename T>
02020 void A_plus_alpha_inplace_functional3D<T>::process (
02021         Box3D domain, ScalarField3D<T>& A)
02022 {
02023     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02024         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02025             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02026                 A.get(iX,iY,iZ) += alpha;
02027             }
02028         }
02029     }
02030 }
02031 
02032 template<typename T>
02033 A_plus_alpha_inplace_functional3D<T>* A_plus_alpha_inplace_functional3D<T>::clone() const {
02034     return new A_plus_alpha_inplace_functional3D<T>(*this);
02035 }
02036 
02037 template<typename T>
02038 void A_plus_alpha_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02039     modified[0] = modif::staticVariables;
02040 }
02041 
02042 template<typename T>
02043 BlockDomain::DomainT A_plus_alpha_inplace_functional3D<T>::appliesTo() const {
02044     return BlockDomain::bulkAndEnvelope;
02045 }
02046 
02047 
02048 /* ******** A_minus_alpha_inplace_functional3D ************************************** */
02049 
02050 template<typename T>
02051 A_minus_alpha_inplace_functional3D<T>::A_minus_alpha_inplace_functional3D(T alpha_)
02052     : alpha(alpha_)
02053 { }
02054 
02055 template<typename T>
02056 void A_minus_alpha_inplace_functional3D<T>::process (
02057         Box3D domain, ScalarField3D<T>& A)
02058 {
02059     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02060         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02061             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02062                 A.get(iX,iY,iZ) -= alpha;
02063             }
02064         }
02065     }
02066 }
02067 
02068 template<typename T>
02069 A_minus_alpha_inplace_functional3D<T>* A_minus_alpha_inplace_functional3D<T>::clone() const {
02070     return new A_minus_alpha_inplace_functional3D<T>(*this);
02071 }
02072 
02073 template<typename T>
02074 void A_minus_alpha_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02075     modified[0] = modif::staticVariables;
02076 }
02077 
02078 template<typename T>
02079 BlockDomain::DomainT A_minus_alpha_inplace_functional3D<T>::appliesTo() const {
02080     return BlockDomain::bulkAndEnvelope;
02081 }
02082 
02083 
02084 /* ******** A_times_alpha_inplace_functional3D ************************************* */
02085 
02086 template<typename T>
02087 A_times_alpha_inplace_functional3D<T>::A_times_alpha_inplace_functional3D(T alpha_)
02088     : alpha(alpha_)
02089 { }
02090 
02091 template<typename T>
02092 void A_times_alpha_inplace_functional3D<T>::process (
02093         Box3D domain, ScalarField3D<T>& A )
02094 {
02095     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02096         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02097             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02098                 A.get(iX,iY,iZ) *= alpha;
02099             }
02100         }
02101     }
02102 }
02103 
02104 template<typename T>
02105 A_times_alpha_inplace_functional3D<T>* A_times_alpha_inplace_functional3D<T>::clone() const {
02106     return new A_times_alpha_inplace_functional3D<T>(*this);
02107 }
02108 
02109 template<typename T>
02110 void A_times_alpha_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02111     modified[0] = modif::staticVariables;
02112 }
02113 
02114 template<typename T>
02115 BlockDomain::DomainT A_times_alpha_inplace_functional3D<T>::appliesTo() const {
02116     return BlockDomain::bulkAndEnvelope;
02117 }
02118 
02119 
02120 /* ******** A_dividedBy_alpha_inplace_functional3D ************************************* */
02121 
02122 template<typename T>
02123 A_dividedBy_alpha_inplace_functional3D<T>::A_dividedBy_alpha_inplace_functional3D(T alpha_)
02124     : alpha(alpha_)
02125 { }
02126 
02127 template<typename T>
02128 void A_dividedBy_alpha_inplace_functional3D<T>::process (
02129         Box3D domain, ScalarField3D<T>& A )
02130 {
02131     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02132         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02133             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02134                 A.get(iX,iY,iZ) /= alpha;
02135             }
02136         }
02137     }
02138 }
02139 
02140 template<typename T>
02141 A_dividedBy_alpha_inplace_functional3D<T>* A_dividedBy_alpha_inplace_functional3D<T>::clone() const {
02142     return new A_dividedBy_alpha_inplace_functional3D<T>(*this);
02143 }
02144 
02145 template<typename T>
02146 void A_dividedBy_alpha_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02147     modified[0] = modif::staticVariables;
02148 }
02149 
02150 template<typename T>
02151 BlockDomain::DomainT A_dividedBy_alpha_inplace_functional3D<T>::appliesTo() const {
02152     return BlockDomain::bulkAndEnvelope;
02153 }
02154 
02155 
02156 /* ******** A_lt_B_functional3D ****************************************** */
02157 
02158 template<typename T>
02159 void A_lt_B_functional3D<T>::processGenericBlocks (
02160         Box3D domain, std::vector<AtomicBlock3D*> fields )
02161 {
02162     PLB_PRECONDITION( fields.size()==3 );
02163     ScalarField3D<T>& A = *dynamic_cast<ScalarField3D<T>*>(fields[0]);
02164     ScalarField3D<T>& B = *dynamic_cast<ScalarField3D<T>*>(fields[1]);
02165     ScalarField3D<int>& result = *dynamic_cast<ScalarField3D<int>*>(fields[2]);
02166     Dot3D offsetB      = computeRelativeDisplacement(A,B);
02167     Dot3D offsetResult = computeRelativeDisplacement(A,result);
02168     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02169         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02170             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02171                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
02172                     = A.get(iX,iY,iZ) < B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z) ? 1:0;
02173             }
02174         }
02175     }
02176 }
02177 
02178 template<typename T>
02179 A_lt_B_functional3D<T>* A_lt_B_functional3D<T>::clone() const {
02180     return new A_lt_B_functional3D<T>(*this);
02181 }
02182 
02183 template<typename T>
02184 void A_lt_B_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02185     modified[0] = modif::nothing;
02186     modified[1] = modif::nothing;
02187     modified[2] = modif::staticVariables;
02188 }
02189 
02190 template<typename T>
02191 BlockDomain::DomainT A_lt_B_functional3D<T>::appliesTo() const {
02192     return BlockDomain::bulkAndEnvelope;
02193 }
02194 
02195 
02196 /* ******** A_gt_B_functional3D ****************************************** */
02197 
02198 template<typename T>
02199 void A_gt_B_functional3D<T>::processGenericBlocks (
02200         Box3D domain, std::vector<AtomicBlock3D*> fields )
02201 {
02202     PLB_PRECONDITION( fields.size()==3 );
02203     ScalarField3D<T>& A = *dynamic_cast<ScalarField3D<T>*>(fields[0]);
02204     ScalarField3D<T>& B = *dynamic_cast<ScalarField3D<T>*>(fields[1]);
02205     ScalarField3D<int>& result = *dynamic_cast<ScalarField3D<int>*>(fields[2]);
02206     Dot3D offsetB      = computeRelativeDisplacement(A,B);
02207     Dot3D offsetResult = computeRelativeDisplacement(A,result);
02208     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02209         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02210             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02211                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
02212                     = A.get(iX,iY,iZ) > B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z) ? 1:0;
02213             }
02214         }
02215     }
02216 }
02217 
02218 template<typename T>
02219 A_gt_B_functional3D<T>* A_gt_B_functional3D<T>::clone() const {
02220     return new A_gt_B_functional3D<T>(*this);
02221 }
02222 
02223 template<typename T>
02224 void A_gt_B_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02225     modified[0] = modif::nothing;
02226     modified[1] = modif::nothing;
02227     modified[2] = modif::staticVariables;
02228 }
02229 
02230 template<typename T>
02231 BlockDomain::DomainT A_gt_B_functional3D<T>::appliesTo() const {
02232     return BlockDomain::bulkAndEnvelope;
02233 }
02234 
02235 
02236 /* ******** A_plus_B_functional3D ****************************************** */
02237 
02238 template<typename T>
02239 void A_plus_B_functional3D<T>::process (
02240         Box3D domain, std::vector<ScalarField3D<T>*> fields )
02241 {
02242     PLB_PRECONDITION( fields.size()==3 );
02243     ScalarField3D<T>& A = *fields[0];
02244     ScalarField3D<T>& B = *fields[1];
02245     ScalarField3D<T>& result = *fields[2];
02246     Dot3D offsetB      = computeRelativeDisplacement(A,B);
02247     Dot3D offsetResult = computeRelativeDisplacement(A,result);
02248     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02249         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02250             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02251                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
02252                     = A.get(iX,iY,iZ) + B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
02253             }
02254         }
02255     }
02256 }
02257 
02258 template<typename T>
02259 A_plus_B_functional3D<T>* A_plus_B_functional3D<T>::clone() const {
02260     return new A_plus_B_functional3D<T>(*this);
02261 }
02262 
02263 template<typename T>
02264 void A_plus_B_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02265     modified[0] = modif::nothing;
02266     modified[1] = modif::nothing;
02267     modified[2] = modif::staticVariables;
02268 }
02269 
02270 template<typename T>
02271 BlockDomain::DomainT A_plus_B_functional3D<T>::appliesTo() const {
02272     return BlockDomain::bulkAndEnvelope;
02273 }
02274 
02275 
02276 /* ******** A_minus_B_functional3D ****************************************** */
02277 
02278 template<typename T>
02279 void A_minus_B_functional3D<T>::process (
02280         Box3D domain, std::vector<ScalarField3D<T>*> fields )
02281 {
02282     PLB_PRECONDITION( fields.size()==3 );
02283     ScalarField3D<T>& A = *fields[0];
02284     ScalarField3D<T>& B = *fields[1];
02285     ScalarField3D<T>& result = *fields[2];
02286     Dot3D offsetB      = computeRelativeDisplacement(A,B);
02287     Dot3D offsetResult = computeRelativeDisplacement(A,result);
02288     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02289         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02290             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02291                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
02292                     = A.get(iX,iY,iZ) - B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
02293             }
02294         }
02295     }
02296 }
02297 
02298 template<typename T>
02299 A_minus_B_functional3D<T>* A_minus_B_functional3D<T>::clone() const {
02300     return new A_minus_B_functional3D<T>(*this);
02301 }
02302 
02303 template<typename T>
02304 void A_minus_B_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02305     modified[0] = modif::nothing;
02306     modified[1] = modif::nothing;
02307     modified[2] = modif::staticVariables;
02308 }
02309 
02310 template<typename T>
02311 BlockDomain::DomainT A_minus_B_functional3D<T>::appliesTo() const {
02312     return BlockDomain::bulkAndEnvelope;
02313 }
02314 
02315 
02316 /* ******** A_times_B_functional3D ****************************************** */
02317 
02318 template<typename T>
02319 void A_times_B_functional3D<T>::process (
02320         Box3D domain, std::vector<ScalarField3D<T>*> fields )
02321 {
02322     PLB_PRECONDITION( fields.size()==3 );
02323     ScalarField3D<T>& A = *fields[0];
02324     ScalarField3D<T>& B = *fields[1];
02325     ScalarField3D<T>& result = *fields[2];
02326     Dot3D offsetB      = computeRelativeDisplacement(A,B);
02327     Dot3D offsetResult = computeRelativeDisplacement(A,result);
02328     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02329         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02330             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02331                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
02332                     = A.get(iX,iY,iZ) * B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
02333             }
02334         }
02335     }
02336 }
02337 
02338 template<typename T>
02339 A_times_B_functional3D<T>* A_times_B_functional3D<T>::clone() const {
02340     return new A_times_B_functional3D<T>(*this);
02341 }
02342 
02343 template<typename T>
02344 void A_times_B_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02345     modified[0] = modif::nothing;
02346     modified[1] = modif::nothing;
02347     modified[2] = modif::staticVariables;
02348 }
02349 
02350 template<typename T>
02351 BlockDomain::DomainT A_times_B_functional3D<T>::appliesTo() const {
02352     return BlockDomain::bulkAndEnvelope;
02353 }
02354 
02355 
02356 /* ******** A_dividedBy_B_functional3D ****************************************** */
02357 
02358 template<typename T>
02359 void A_dividedBy_B_functional3D<T>::process (
02360         Box3D domain, std::vector<ScalarField3D<T>*> fields )
02361 {
02362     PLB_PRECONDITION( fields.size()==3 );
02363     ScalarField3D<T>& A = *fields[0];
02364     ScalarField3D<T>& B = *fields[1];
02365     ScalarField3D<T>& result = *fields[2];
02366     Dot3D offsetB      = computeRelativeDisplacement(A,B);
02367     Dot3D offsetResult = computeRelativeDisplacement(A,result);
02368     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02369         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02370             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02371                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
02372                     = A.get(iX,iY,iZ) / B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
02373             }
02374         }
02375     }
02376 }
02377 
02378 template<typename T>
02379 A_dividedBy_B_functional3D<T>* A_dividedBy_B_functional3D<T>::clone() const {
02380     return new A_dividedBy_B_functional3D<T>(*this);
02381 }
02382 
02383 template<typename T>
02384 void A_dividedBy_B_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02385     modified[0] = modif::nothing;
02386     modified[1] = modif::nothing;
02387     modified[2] = modif::staticVariables;
02388 }
02389 
02390 template<typename T>
02391 BlockDomain::DomainT A_dividedBy_B_functional3D<T>::appliesTo() const {
02392     return BlockDomain::bulkAndEnvelope;
02393 }
02394 
02395 
02396 /* ******** A_plus_B_inplace_functional3D ****************************************** */
02397 
02398 template<typename T>
02399 void A_plus_B_inplace_functional3D<T>::process (
02400         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& B)
02401 {
02402     Dot3D offset = computeRelativeDisplacement(A,B);
02403     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02404         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02405             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02406                 A.get(iX,iY,iZ) += B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
02407             }
02408         }
02409     }
02410 }
02411 
02412 template<typename T>
02413 A_plus_B_inplace_functional3D<T>* A_plus_B_inplace_functional3D<T>::clone() const {
02414     return new A_plus_B_inplace_functional3D<T>(*this);
02415 }
02416 
02417 template<typename T>
02418 void A_plus_B_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02419     modified[0] = modif::staticVariables;
02420     modified[1] = modif::nothing;
02421 }
02422 
02423 template<typename T>
02424 BlockDomain::DomainT A_plus_B_inplace_functional3D<T>::appliesTo() const {
02425     return BlockDomain::bulkAndEnvelope;
02426 }
02427 
02428 
02429 /* ******** A_minus_B_inplace_functional3D ****************************************** */
02430 
02431 template<typename T>
02432 void A_minus_B_inplace_functional3D<T>::process (
02433         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& B)
02434 {
02435     Dot3D offset = computeRelativeDisplacement(A,B);
02436     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02437         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02438             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02439                 A.get(iX,iY,iZ) -= B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
02440             }
02441         }
02442     }
02443 }
02444 
02445 template<typename T>
02446 A_minus_B_inplace_functional3D<T>* A_minus_B_inplace_functional3D<T>::clone() const {
02447     return new A_minus_B_inplace_functional3D<T>(*this);
02448 }
02449 
02450 template<typename T>
02451 void A_minus_B_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02452     modified[0] = modif::staticVariables;
02453     modified[1] = modif::nothing;
02454 }
02455 
02456 template<typename T>
02457 BlockDomain::DomainT A_minus_B_inplace_functional3D<T>::appliesTo() const {
02458     return BlockDomain::bulkAndEnvelope;
02459 }
02460 
02461 
02462 /* ******** A_times_B_inplace_functional3D ****************************************** */
02463 
02464 template<typename T>
02465 void A_times_B_inplace_functional3D<T>::process (
02466         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& B)
02467 {
02468     Dot3D offset = computeRelativeDisplacement(A,B);
02469     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02470         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02471             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02472                 A.get(iX,iY,iZ) *= B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
02473             }
02474         }
02475     }
02476 }
02477 
02478 template<typename T>
02479 A_times_B_inplace_functional3D<T>* A_times_B_inplace_functional3D<T>::clone() const {
02480     return new A_times_B_inplace_functional3D<T>(*this);
02481 }
02482 
02483 template<typename T>
02484 void A_times_B_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02485     modified[0] = modif::staticVariables;
02486     modified[1] = modif::nothing;
02487 }
02488 
02489 template<typename T>
02490 BlockDomain::DomainT A_times_B_inplace_functional3D<T>::appliesTo() const {
02491     return BlockDomain::bulkAndEnvelope;
02492 }
02493 
02494 
02495 /* ******** A_dividedBy_B_inplace_functional3D ****************************************** */
02496 
02497 template<typename T>
02498 void A_dividedBy_B_inplace_functional3D<T>::process (
02499         Box3D domain, ScalarField3D<T>& A, ScalarField3D<T>& B)
02500 {
02501     Dot3D offset = computeRelativeDisplacement(A,B);
02502     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02503         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02504             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02505                 A.get(iX,iY,iZ) -= B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
02506             }
02507         }
02508     }
02509 }
02510 
02511 template<typename T>
02512 A_dividedBy_B_inplace_functional3D<T>* A_dividedBy_B_inplace_functional3D<T>::clone() const {
02513     return new A_dividedBy_B_inplace_functional3D<T>(*this);
02514 }
02515 
02516 template<typename T>
02517 void A_dividedBy_B_inplace_functional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02518     modified[0] = modif::staticVariables;
02519     modified[1] = modif::nothing;
02520 }
02521 
02522 template<typename T>
02523 BlockDomain::DomainT A_dividedBy_B_inplace_functional3D<T>::appliesTo() const {
02524     return BlockDomain::bulkAndEnvelope;
02525 }
02526 
02527 
02528 /* *************** PART III ****************************************** */
02529 /* *************** Analysis of the tensor-field ********************** */
02530 /* ******************************************************************* */
02531 
02533 namespace fdDataField {
02534 
02535 template<typename T, int nDim>
02536 inline T bulkXderiv (
02537         TensorField3D<T,nDim> const& velocity, plint iX, plint iY, plint iZ, int iD )
02538 {
02539     T dxu = fd::ctl_diff( velocity.get(iX+1,iY,iZ)[iD],
02540                           velocity.get(iX-1,iY,iZ)[iD] );
02541     return dxu;
02542 }
02543 
02544 template<typename T, int nDim>
02545 inline T bulkYderiv (
02546         TensorField3D<T,nDim> const& velocity, plint iX, plint iY, plint iZ, int iD )
02547 {
02548     T dyu = fd::ctl_diff( velocity.get(iX,iY+1,iZ)[iD],
02549                           velocity.get(iX,iY-1,iZ)[iD] );
02550     return dyu;
02551 }
02552 
02553 template<typename T, int nDim>
02554 inline T bulkZderiv (
02555         TensorField3D<T,nDim> const& velocity, plint iX, plint iY, plint iZ, int iD )
02556 {
02557     T dzu = fd::ctl_diff( velocity.get(iX,iY,iZ+1)[iD],
02558                           velocity.get(iX,iY,iZ-1)[iD] );
02559     return dzu;
02560 }
02561 
02562 template<typename T, int nDim>
02563 inline T planeXderiv (
02564         TensorField3D<T,nDim> const& velocity, int direction, int orientation,
02565         plint iX, plint iY, plint iZ, int iD )
02566 {
02567     if (direction==0) {
02568         return -orientation *
02569             fd::o1_fwd_diff( velocity.get(iX              ,iY,iZ)[iD],
02570                              velocity.get(iX-1*orientation,iY,iZ)[iD] );
02571     }
02572     else {
02573         return bulkXderiv(velocity, iX,iY,iZ, iD);
02574     }
02575 }
02576 
02577 template<typename T, int nDim>
02578 inline T planeYderiv (
02579         TensorField3D<T,nDim> const& velocity, int direction, int orientation,
02580         plint iX, plint iY, plint iZ, int iD )
02581 {
02582     if (direction==1) {
02583         return -orientation *
02584             fd::o1_fwd_diff( velocity.get(iX,iY              ,iZ)[iD],
02585                              velocity.get(iX,iY-1*orientation,iZ)[iD] );
02586     }
02587     else {
02588         return bulkYderiv(velocity, iX,iY,iZ, iD);
02589     }
02590 }
02591 
02592 template<typename T, int nDim>
02593 inline T planeZderiv (
02594         TensorField3D<T,nDim> const& velocity, int direction, int orientation,
02595         plint iX, plint iY, plint iZ, int iD )
02596 {
02597     if (direction==2) {
02598         return -orientation *
02599             fd::o1_fwd_diff( velocity.get(iX,iY,iZ              )[iD],
02600                              velocity.get(iX,iY,iZ-1*orientation)[iD] );
02601     }
02602     else {
02603         return bulkZderiv(velocity, iX,iY,iZ, iD);
02604     }
02605 }
02606 
02607 template<typename T, int nDim>
02608 inline T edgeXderiv (
02609         TensorField3D<T,nDim> const& velocity,
02610         int plane, int direction1, int direction2,
02611         plint iX, plint iY, plint iZ, int iD )
02612 {
02613     if (plane==0) {
02614         return bulkXderiv(velocity, iX,iY,iZ, iD);
02615     }
02616     else {
02617         int orientation = plane==1 ? direction2 : direction1;
02618         return -orientation *
02619             fd::o1_fwd_diff( velocity.get(iX              ,iY,iZ)[iD],
02620                              velocity.get(iX-1*orientation,iY,iZ)[iD] );
02621     }
02622 }
02623 
02624 template<typename T, int nDim>
02625 inline T edgeYderiv (
02626         TensorField3D<T,nDim> const& velocity,
02627         int plane, int direction1, int direction2,
02628         plint iX, plint iY, plint iZ, int iD )
02629 {
02630     if (plane==1) {
02631         return bulkYderiv(velocity, iX,iY,iZ, iD);
02632     }
02633     else {
02634         int orientation = plane==0 ? direction1 : direction2;
02635         return -orientation *
02636             fd::o1_fwd_diff( velocity.get(iX,iY              ,iZ)[iD],
02637                              velocity.get(iX,iY-1*orientation,iZ)[iD] );
02638     }
02639 }
02640 
02641 template<typename T, int nDim>
02642 inline T edgeZderiv (
02643         TensorField3D<T,nDim> const& velocity,
02644         int plane, int direction1, int direction2,
02645         plint iX, plint iY, plint iZ, int iD )
02646 {
02647     if (plane==2) {
02648         return bulkZderiv(velocity, iX,iY,iZ, iD);
02649     }
02650     else {
02651         int orientation = plane==0 ? direction2 : direction1;
02652         return -orientation *
02653             fd::o1_fwd_diff( velocity.get(iX,iY,iZ              )[iD],
02654                              velocity.get(iX,iY,iZ-1*orientation)[iD] );
02655     }
02656 }
02657 
02658 template<typename T, int nDim>
02659 inline T cornerXderiv (
02660         TensorField3D<T,nDim> const& velocity,
02661         int normalX, int normalY, int normalZ,
02662         plint iX, plint iY, plint iZ, int iD )
02663 {
02664     int orientation = normalX;
02665     return -orientation *
02666         fd::o1_fwd_diff( velocity.get(iX              ,iY,iZ)[iD],
02667                          velocity.get(iX-1*orientation,iY,iZ)[iD] );
02668 }
02669 
02670 template<typename T, int nDim>
02671 inline T cornerYderiv (
02672         TensorField3D<T,nDim> const& velocity,
02673         int normalX, int normalY, int normalZ,
02674         plint iX, plint iY, plint iZ, int iD )
02675 {
02676     int orientation = normalY;
02677     return -orientation *
02678         fd::o1_fwd_diff( velocity.get(iX,iY              ,iZ)[iD],
02679                          velocity.get(iX,iY-1*orientation,iZ)[iD] );
02680 }
02681 
02682 template<typename T, int nDim>
02683 inline T cornerZderiv (
02684         TensorField3D<T,nDim> const& velocity,
02685         int normalX, int normalY, int normalZ,
02686         plint iX, plint iY, plint iZ, int iD )
02687 {
02688     int orientation = normalZ;
02689     return -orientation *
02690         fd::o1_fwd_diff( velocity.get(iX,iY,iZ              )[iD],
02691                          velocity.get(iX,iY,iZ-1*orientation)[iD] );
02692 }
02693 
02694 
02695 template<typename T, int nDim>
02696 inline T bulkVorticityX(TensorField3D<T,nDim> const& velocity, plint iX, plint iY, plint iZ )
02697 {
02698     T dyuz = fdDataField::bulkYderiv(velocity, iX,iY,iZ, 2);
02699     T dzuy = fdDataField::bulkZderiv(velocity, iX,iY,iZ, 1);
02700 
02701     return dyuz - dzuy;
02702 }
02703 
02704 template<typename T, int nDim>
02705 inline T bulkVorticityY(TensorField3D<T,nDim> const& velocity, plint iX, plint iY, plint iZ )
02706 {
02707     T dzux = fdDataField::bulkZderiv(velocity, iX,iY,iZ, 0);
02708     T dxuz = fdDataField::bulkXderiv(velocity, iX,iY,iZ, 2);
02709 
02710     return dzux - dxuz;
02711 }
02712 
02713 template<typename T, int nDim>
02714 inline T bulkVorticityZ(TensorField3D<T,nDim> const& velocity, plint iX, plint iY, plint iZ )
02715 {
02716     T dxuy = fdDataField::bulkXderiv(velocity, iX,iY,iZ, 1);
02717     T dyux = fdDataField::bulkYderiv(velocity, iX,iY,iZ, 0);
02718 
02719     return dxuy - dyux;
02720 }
02721 
02722 template<typename T, int nDim>
02723 inline T planeVorticityX( TensorField3D<T,nDim> const& velocity, int direction, int orientation,
02724                           plint iX, plint iY, plint iZ )
02725 {
02726     T dyuz = fdDataField::planeYderiv(velocity,direction,orientation, iX,iY,iZ, 2);
02727     T dzuy = fdDataField::planeZderiv(velocity,direction,orientation, iX,iY,iZ, 1);
02728 
02729     return dyuz - dzuy;
02730 }
02731 
02732 template<typename T, int nDim>
02733 inline T planeVorticityY( TensorField3D<T,nDim> const& velocity, int direction, int orientation,
02734                           plint iX, plint iY, plint iZ )
02735 {
02736     T dzux = fdDataField::planeZderiv(velocity,direction,orientation, iX,iY,iZ, 0);
02737     T dxuz = fdDataField::planeXderiv(velocity,direction,orientation, iX,iY,iZ, 2);
02738 
02739     return dzux - dxuz;
02740 }
02741 
02742 template<typename T, int nDim>
02743 inline T planeVorticityZ( TensorField3D<T,nDim> const& velocity, int direction, int orientation,
02744                           plint iX, plint iY, plint iZ )
02745 {
02746     T dxuy = fdDataField::planeXderiv(velocity,direction,orientation, iX,iY,iZ, 1);
02747     T dyux = fdDataField::planeYderiv(velocity,direction,orientation, iX,iY,iZ, 0);
02748 
02749     return dxuy - dyux;
02750 }
02751 
02752 template<typename T, int nDim>
02753 inline T edgeVorticityX( TensorField3D<T,nDim> const& velocity, int plane, int normal1, int normal2,
02754                          plint iX, plint iY, plint iZ )
02755 {
02756     T dyuz = fdDataField::edgeYderiv(velocity,plane,normal1,normal2, iX,iY,iZ, 2);
02757     T dzuy = fdDataField::edgeZderiv(velocity,plane,normal1,normal2, iX,iY,iZ, 1);
02758 
02759     return dyuz - dzuy;
02760 }
02761 
02762 template<typename T, int nDim>
02763 inline T edgeVorticityY( TensorField3D<T,nDim> const& velocity, int plane, int normal1, int normal2,
02764                          plint iX, plint iY, plint iZ )
02765 {
02766     T dzux = fdDataField::edgeZderiv(velocity,plane,normal1,normal2, iX,iY,iZ, 0);
02767     T dxuz = fdDataField::edgeXderiv(velocity,plane,normal1,normal2, iX,iY,iZ, 2);
02768 
02769     return dzux - dxuz;
02770 }
02771 
02772 template<typename T, int nDim>
02773 inline T edgeVorticityZ( TensorField3D<T,nDim> const& velocity, int plane, int normal1, int normal2,
02774                          plint iX, plint iY, plint iZ )
02775 {
02776     T dxuy = fdDataField::edgeXderiv(velocity,plane,normal1,normal2, iX,iY,iZ, 1);
02777     T dyux = fdDataField::edgeYderiv(velocity,plane,normal1,normal2, iX,iY,iZ, 0);
02778 
02779     return dxuy - dyux;
02780 }
02781 
02782 template<typename T, int nDim>
02783 inline T cornerVorticityX( TensorField3D<T,nDim> const& velocity, int normalX, int normalY, int normalZ,
02784                            plint iX, plint iY, plint iZ )
02785 {
02786     T dyuz = fdDataField::cornerYderiv(velocity,normalX,normalY,normalZ, iX,iY,iZ, 2);
02787     T dzuy = fdDataField::cornerZderiv(velocity,normalX,normalY,normalZ, iX,iY,iZ, 1);
02788 
02789     return dyuz - dzuy;
02790 }
02791 
02792 template<typename T, int nDim>
02793 inline T cornerVorticityY( TensorField3D<T,nDim> const& velocity, int normalX, int normalY, int normalZ,
02794                            plint iX, plint iY, plint iZ )
02795 {
02796     T dzux = fdDataField::cornerZderiv(velocity,normalX,normalY,normalZ, iX,iY,iZ, 0);
02797     T dxuz = fdDataField::cornerXderiv(velocity,normalX,normalY,normalZ, iX,iY,iZ, 2);
02798 
02799     return dzux - dxuz;
02800 }
02801 
02802 template<typename T, int nDim>
02803 inline T cornerVorticityZ( TensorField3D<T,nDim> const& velocity, int normalX, int normalY, int normalZ,
02804                            plint iX, plint iY, plint iZ )
02805 {
02806     T dxuy = fdDataField::cornerXderiv(velocity,normalX,normalY,normalZ, iX,iY,iZ, 1);
02807     T dyux = fdDataField::cornerYderiv(velocity,normalX,normalY,normalZ, iX,iY,iZ, 0);
02808 
02809     return dxuy - dyux;
02810 }
02811 
02812 }  // fdDataField
02813 
02814 
02815 template<typename T1, typename T2, int nDim>
02816 void CopyConvertTensorFunctional3D<T1,T2,nDim>::process (
02817         Box3D domain, TensorField3D<T1,nDim>& field1,
02818                       TensorField3D<T2,nDim>& field2 )
02819 {
02820     Dot3D offset = computeRelativeDisplacement(field1, field2);
02821 
02822     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02823         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02824             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02825                 for (int iDim=0; iDim<nDim; ++iDim) {
02826                     field2.get(iX+offset.x,iY+offset.y,iZ+offset.z)[iDim] =
02827                         (T2) field1.get(iX,iY,iZ)[iDim];
02828                 }
02829             }
02830         }
02831     }
02832 }
02833 
02834 template<typename T1, typename T2, int nDim>
02835 CopyConvertTensorFunctional3D<T1,T2,nDim>* CopyConvertTensorFunctional3D<T1,T2,nDim>::clone() const
02836 {
02837     return new CopyConvertTensorFunctional3D<T1,T2,nDim>(*this);
02838 }
02839 
02840 template<typename T1, typename T2, int nDim>
02841 void CopyConvertTensorFunctional3D<T1,T2,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02842     modified[0] = modif::nothing;
02843     modified[1] = modif::staticVariables;
02844 }
02845 
02846 template<typename T1, typename T2, int nDim>
02847 BlockDomain::DomainT CopyConvertTensorFunctional3D<T1,T2,nDim>::appliesTo() const {
02848     return BlockDomain::bulk;
02849 }
02850 
02851 
02852 template<typename T, int nDim>
02853 void ExtractTensorSubDomainFunctional3D<T,nDim>::process (
02854         Box3D domain, TensorField3D<T,nDim>& field1,
02855                       TensorField3D<T,nDim>& field2 )
02856 {
02857     Dot3D offset = computeRelativeDisplacement(field1, field2);
02858     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02859         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02860             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02861                 for (int iDim=0; iDim<nDim; ++iDim) {
02862                     field2.get(iX+offset.x,iY+offset.y,iZ+offset.z)[iDim]
02863                         = field1.get(iX,iY,iZ)[iDim];
02864                 }
02865             }
02866         }
02867     }
02868 }
02869 
02870 template<typename T, int nDim>
02871 ExtractTensorSubDomainFunctional3D<T,nDim>* ExtractTensorSubDomainFunctional3D<T,nDim>::clone() const
02872 {
02873     return new ExtractTensorSubDomainFunctional3D<T,nDim>(*this);
02874 }
02875 
02876 template<typename T, int nDim>
02877 void ExtractTensorSubDomainFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02878     modified[0] = modif::nothing;
02879     modified[1] = modif::staticVariables;
02880 }
02881 
02882 template<typename T, int nDim>
02883 BlockDomain::DomainT ExtractTensorSubDomainFunctional3D<T,nDim>::appliesTo() const {
02884     return BlockDomain::bulk;
02885 }
02886 
02887 
02888 template<typename T, int nDim>
02889 ExtractTensorComponentFunctional3D<T,nDim>::ExtractTensorComponentFunctional3D(int iComponent_)
02890     : iComponent(iComponent_)
02891 { }
02892 
02893 template<typename T, int nDim>
02894 void ExtractTensorComponentFunctional3D<T,nDim>::process (
02895         Box3D domain, ScalarField3D<T>& scalarField,
02896                       TensorField3D<T,nDim>& tensorField )
02897 {
02898     Dot3D offset = computeRelativeDisplacement(scalarField, tensorField);
02899     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02900         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02901             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02902                 scalarField.get(iX,iY,iZ)
02903                     = tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z)[iComponent];
02904             }
02905         }
02906     }
02907 }
02908 
02909 template<typename T, int nDim>
02910 ExtractTensorComponentFunctional3D<T,nDim>* ExtractTensorComponentFunctional3D<T,nDim>::clone() const
02911 {
02912     return new ExtractTensorComponentFunctional3D<T,nDim>(*this);
02913 }
02914 
02915 template<typename T, int nDim>
02916 void ExtractTensorComponentFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02917     modified[0] = modif::staticVariables;
02918     modified[1] = modif::nothing;
02919 }
02920 
02921 template<typename T, int nDim>
02922 BlockDomain::DomainT ExtractTensorComponentFunctional3D<T,nDim>::appliesTo() const {
02923     return BlockDomain::bulkAndEnvelope;
02924 }
02925 
02926 
02927 template<typename T, int nDim>
02928 void ComputeNormFunctional3D<T,nDim>::process (
02929         Box3D domain, ScalarField3D<T>& scalarField,
02930                       TensorField3D<T,nDim>& tensorField )
02931 {
02932     Dot3D offset = computeRelativeDisplacement(scalarField, tensorField);
02933     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02934         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02935             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02936                 scalarField.get(iX,iY,iZ) = std::sqrt( VectorTemplateImpl<T,nDim>::normSqr (
02937                                                            tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z) ) );
02938             }
02939         }
02940     }
02941 }
02942 
02943 template<typename T, int nDim>
02944 ComputeNormFunctional3D<T,nDim>* ComputeNormFunctional3D<T,nDim>::clone() const
02945 {
02946     return new ComputeNormFunctional3D<T,nDim>(*this);
02947 }
02948 
02949 template<typename T, int nDim>
02950 void ComputeNormFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02951     modified[0] = modif::staticVariables;
02952     modified[1] = modif::nothing;
02953 }
02954 
02955 template<typename T, int nDim>
02956 BlockDomain::DomainT ComputeNormFunctional3D<T,nDim>::appliesTo() const {
02957     return BlockDomain::bulkAndEnvelope;
02958 }
02959 
02960 
02961 template<typename T, int nDim>
02962 void ComputeNormSqrFunctional3D<T,nDim>::process (
02963         Box3D domain, ScalarField3D<T>& scalarField,
02964                       TensorField3D<T,nDim>& tensorField )
02965 {
02966     Dot3D offset = computeRelativeDisplacement(scalarField, tensorField);
02967     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02968         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02969             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
02970                 scalarField.get(iX,iY,iZ) = VectorTemplateImpl<T,nDim>::normSqr (
02971                                             tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z) );
02972             }
02973         }
02974     }
02975 }
02976 
02977 template<typename T, int nDim>
02978 ComputeNormSqrFunctional3D<T,nDim>* ComputeNormSqrFunctional3D<T,nDim>::clone() const
02979 {
02980     return new ComputeNormSqrFunctional3D<T,nDim>(*this);
02981 }
02982 
02983 template<typename T, int nDim>
02984 void ComputeNormSqrFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02985     modified[0] = modif::staticVariables;
02986     modified[1] = modif::nothing;
02987 }
02988 
02989 template<typename T, int nDim>
02990 BlockDomain::DomainT ComputeNormSqrFunctional3D<T,nDim>::appliesTo() const {
02991     return BlockDomain::bulkAndEnvelope;
02992 }
02993 
02994 
02995 template<typename T>
02996 void ComputeSymmetricTensorNormFunctional3D<T>::process (
02997         Box3D domain, ScalarField3D<T>& scalarField,
02998                       TensorField3D<T,6>& tensorField )
02999 {
03000     typedef SymmetricTensorImpl<T,3> tensor;
03001     Dot3D offset = computeRelativeDisplacement(scalarField, tensorField);
03002     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03003         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03004             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03005                 Array<T,6>& el = tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03006                 scalarField.get(iX,iY,iZ) = std::sqrt ( 
03007                         // Count diagonal components once ...
03008                                 util::sqr(el[tensor::xx]) + util::sqr(el[tensor::yy]) + util::sqr(el[tensor::zz]) +
03009                         // .. and off-diagonal components twice, due to symmetry.
03010                         (T)2 * (util::sqr(el[tensor::xy]) + util::sqr(el[tensor::xz]) +util::sqr(el[tensor::yz])) );
03011             }
03012         }
03013     }
03014 }
03015 
03016 template<typename T>
03017 ComputeSymmetricTensorNormFunctional3D<T>* ComputeSymmetricTensorNormFunctional3D<T>::clone() const
03018 {
03019     return new ComputeSymmetricTensorNormFunctional3D<T>(*this);
03020 }
03021 
03022 template<typename T>
03023 void ComputeSymmetricTensorNormFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03024     modified[0] = modif::staticVariables;
03025     modified[1] = modif::nothing;
03026 }
03027 
03028 template<typename T>
03029 BlockDomain::DomainT ComputeSymmetricTensorNormFunctional3D<T>::appliesTo() const {
03030     return BlockDomain::bulkAndEnvelope;
03031 }
03032 
03033 
03034 template<typename T>
03035 void ComputeSymmetricTensorNormSqrFunctional3D<T>::process (
03036         Box3D domain, ScalarField3D<T>& scalarField,
03037                       TensorField3D<T,6>& tensorField )
03038 {
03039     typedef SymmetricTensorImpl<T,3> tensor;
03040     Dot3D offset = computeRelativeDisplacement(scalarField, tensorField);
03041     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03042         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03043             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03044                 Array<T,6>& el = tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03045                 scalarField.get(iX,iY,iZ) = 
03046                         // Count diagonal components once ...
03047                                 util::sqr(el[tensor::xx]) + util::sqr(el[tensor::yy]) + util::sqr(el[tensor::zz]) +
03048                         // .. and off-diagonal components twice, due to symmetry.
03049                         (T)2 * (util::sqr(el[tensor::xy]) + util::sqr(el[tensor::xz]) +util::sqr(el[tensor::yz]));
03050             }
03051         }
03052     }
03053 }
03054 
03055 template<typename T>
03056 ComputeSymmetricTensorNormSqrFunctional3D<T>* ComputeSymmetricTensorNormSqrFunctional3D<T>::clone() const
03057 {
03058     return new ComputeSymmetricTensorNormSqrFunctional3D<T>(*this);
03059 }
03060 
03061 template<typename T>
03062 void ComputeSymmetricTensorNormSqrFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03063     modified[0] = modif::staticVariables;
03064     modified[1] = modif::nothing;
03065 }
03066 
03067 template<typename T>
03068 BlockDomain::DomainT ComputeSymmetricTensorNormSqrFunctional3D<T>::appliesTo() const {
03069     return BlockDomain::bulkAndEnvelope;
03070 }
03071 
03072 
03073 
03074 template<typename T>
03075 void ComputeSymmetricTensorTraceFunctional3D<T>::process (
03076         Box3D domain, ScalarField3D<T>& scalarField,
03077                       TensorField3D<T,6>& tensorField )
03078 {
03079     typedef SymmetricTensorImpl<T,3> tensor;
03080     Dot3D offset = computeRelativeDisplacement(scalarField, tensorField);
03081     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03082         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03083             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03084                 Array<T,6>& el = tensorField.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03085                 scalarField.get(iX,iY,iZ) = el[tensor::xx] + el[tensor::yy] + el[tensor::zz];
03086             }
03087         }
03088     }
03089 }
03090 
03091 template<typename T>
03092 ComputeSymmetricTensorTraceFunctional3D<T>* ComputeSymmetricTensorTraceFunctional3D<T>::clone() const
03093 {
03094     return new ComputeSymmetricTensorTraceFunctional3D<T>(*this);
03095 }
03096 
03097 template<typename T>
03098 void ComputeSymmetricTensorTraceFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03099     modified[0] = modif::staticVariables;
03100     modified[1] = modif::nothing;
03101 }
03102 
03103 template<typename T>
03104 BlockDomain::DomainT ComputeSymmetricTensorTraceFunctional3D<T>::appliesTo() const {
03105     return BlockDomain::bulkAndEnvelope;
03106 }
03107 
03108 
03109 template<typename T>
03110 void BoxBulkGradientFunctional3D<T>::process (
03111         Box3D domain, ScalarField3D<T>& phi,
03112                       TensorField3D<T,3>& gradient )
03113 {
03114     Dot3D offset = computeRelativeDisplacement(phi, gradient);
03115     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03116         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03117             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03118                 plint iX2 = iX+offset.x;
03119                 plint iY2 = iY+offset.y;
03120                 plint iZ2 = iZ+offset.z;
03121                 gradient.get(iX2,iY2,iZ2)[0] =
03122                     fdDataField::bulkXderiv(phi, iX,iY,iZ);
03123                 gradient.get(iX2,iY2,iZ2)[1] =
03124                     fdDataField::bulkYderiv(phi, iX,iY,iZ);
03125                 gradient.get(iX2,iY2,iZ2)[2] =
03126                     fdDataField::bulkZderiv(phi, iX,iY,iZ);
03127             }
03128         }
03129     }
03130 }
03131 
03132 template<typename T>
03133 BoxBulkGradientFunctional3D<T>* BoxBulkGradientFunctional3D<T>::clone() const
03134 {
03135     return new BoxBulkGradientFunctional3D<T>(*this);
03136 }
03137 
03138 template<typename T>
03139 void BoxBulkGradientFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03140     modified[0] = modif::nothing;
03141     modified[1] = modif::staticVariables;
03142 }
03143 
03144 template<typename T>
03145 BlockDomain::DomainT BoxBulkGradientFunctional3D<T>::appliesTo() const {
03146     return BlockDomain::bulk;
03147 }
03148 
03149 
03150 
03151 template<typename T>
03152 void BoxGradientFunctional3D<T>::processBulk (
03153         Box3D domain, ScalarField3D<T>& phi, TensorField3D<T,3>& gradient )
03154 {
03155     Dot3D offset = computeRelativeDisplacement(phi, gradient);
03156     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03157         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03158             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03159                 plint iX2 = iX+offset.x;
03160                 plint iY2 = iY+offset.y;
03161                 plint iZ2 = iZ+offset.z;
03162                 gradient.get(iX2,iY2,iZ2)[0] =
03163                     fdDataField::bulkXderiv(phi, iX,iY,iZ);
03164                 gradient.get(iX2,iY2,iZ2)[1] =
03165                     fdDataField::bulkYderiv(phi, iX,iY,iZ);
03166                 gradient.get(iX2,iY2,iZ2)[2] =
03167                     fdDataField::bulkZderiv(phi, iX,iY,iZ);
03168             }
03169         }
03170     }
03171 }
03172 
03173 template<typename T>
03174 void BoxGradientFunctional3D<T>::processPlane (
03175         int direction, int orientation, Box3D domain,
03176         ScalarField3D<T>& phi, TensorField3D<T,3>& gradient )
03177 {
03178     Dot3D offset = computeRelativeDisplacement(phi, gradient);
03179     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03180         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03181             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03182                 plint iX2 = iX+offset.x;
03183                 plint iY2 = iY+offset.y;
03184                 plint iZ2 = iZ+offset.z;
03185                 gradient.get(iX2,iY2,iZ2)[0] =
03186                     fdDataField::planeXderiv(phi,direction,orientation, iX,iY,iZ);
03187                 gradient.get(iX2,iY2,iZ2)[1] =
03188                     fdDataField::planeYderiv(phi,direction,orientation, iX,iY,iZ);
03189                 gradient.get(iX2,iY2,iZ2)[2] =
03190                     fdDataField::planeZderiv(phi,direction,orientation, iX,iY,iZ);
03191             }
03192         }
03193     }
03194 }
03195 
03196 template<typename T>
03197 void BoxGradientFunctional3D<T>::processEdge (
03198         int plane, int normal1, int normal2, Box3D domain,
03199         ScalarField3D<T>& phi, TensorField3D<T,3>& gradient )
03200 {
03201     Dot3D offset = computeRelativeDisplacement(phi, gradient);
03202     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03203         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03204             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03205                 plint iX2 = iX+offset.x;
03206                 plint iY2 = iY+offset.y;
03207                 plint iZ2 = iZ+offset.z;
03208                 gradient.get(iX2,iY2,iZ2)[0] =
03209                     fdDataField::edgeXderiv(phi,plane,normal1,normal2, iX,iY,iZ);
03210                 gradient.get(iX2,iY2,iZ2)[1] =
03211                     fdDataField::edgeYderiv(phi,plane,normal1,normal2, iX,iY,iZ);
03212                 gradient.get(iX2,iY2,iZ2)[2] =
03213                     fdDataField::edgeZderiv(phi,plane,normal1,normal2, iX,iY,iZ);
03214             }
03215         }
03216     }
03217 }
03218 
03219 template<typename T>
03220 void BoxGradientFunctional3D<T>::processCorner (
03221         int normalX, int normalY, int normalZ, Box3D domain,
03222         ScalarField3D<T>& phi, TensorField3D<T,3>& gradient )
03223 {
03224 
03225     Dot3D offset = computeRelativeDisplacement(phi, gradient);
03226     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03227         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03228             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03229                 plint iX2 = iX+offset.x;
03230                 plint iY2 = iY+offset.y;
03231                 plint iZ2 = iZ+offset.z;
03232                 gradient.get(iX2,iY2,iZ2)[0] =
03233                     fdDataField::cornerXderiv(phi,normalX,normalY,normalZ, iX,iY,iZ);
03234                 gradient.get(iX2,iY2,iZ2)[1] =
03235                     fdDataField::cornerYderiv(phi,normalX,normalY,normalZ, iX,iY,iZ);
03236                 gradient.get(iX2,iY2,iZ2)[2] =
03237                     fdDataField::cornerZderiv(phi,normalX,normalY,normalZ, iX,iY,iZ);
03238             }
03239         }
03240     }
03241 }
03242 
03243 
03244 template<typename T>
03245 BoxGradientFunctional3D<T>* BoxGradientFunctional3D<T>::clone() const
03246 {
03247     return new BoxGradientFunctional3D<T>(*this);
03248 }
03249 
03250 template<typename T>
03251 void BoxGradientFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03252     modified[0] = modif::nothing;
03253     modified[1] = modif::staticVariables;
03254 }
03255 
03256 
03257 template<typename T>
03258 BlockDomain::DomainT BoxGradientFunctional3D<T>::appliesTo() const {
03259     // Don't apply to envelope, because nearest neighbors need to be accessed.
03260     return BlockDomain::bulk;
03261 }
03262 
03263 
03264 template<typename T, int nDim>
03265 void BoxBulkVorticityFunctional3D<T,nDim>::process (
03266         Box3D domain, TensorField3D<T,nDim>& velocity,
03267                       TensorField3D<T,nDim>& vorticity )
03268 {
03269     Dot3D offset = computeRelativeDisplacement(velocity, vorticity);
03270     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03271         plint iX2 = iX+offset.x;
03272         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03273             plint iY2 = iY+offset.y;
03274             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03275                 plint iZ2 = iZ+offset.z;
03276                 vorticity.get(iX2,iY2,iZ2)[0] =
03277                     fdDataField::bulkVorticityX(velocity, iX,iY,iZ);
03278                 vorticity.get(iX2,iY2,iZ2)[1] = 
03279                     fdDataField::bulkVorticityY(velocity, iX,iY,iZ);
03280                 vorticity.get(iX2,iY2,iZ2)[2] = 
03281                     fdDataField::bulkVorticityZ(velocity, iX,iY,iZ);
03282             }
03283         }
03284     }
03285 }
03286 
03287 template<typename T, int nDim>
03288 BoxBulkVorticityFunctional3D<T,nDim>* BoxBulkVorticityFunctional3D<T,nDim>::clone() const
03289 {
03290     return new BoxBulkVorticityFunctional3D<T,nDim>(*this);
03291 }
03292 
03293 template<typename T, int nDim>
03294 void BoxBulkVorticityFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03295     modified[0] = modif::nothing;
03296     modified[1] = modif::staticVariables;
03297 }
03298 
03299 template<typename T, int nDim>
03300 BlockDomain::DomainT BoxBulkVorticityFunctional3D<T,nDim>::appliesTo() const {
03301     return BlockDomain::bulk;
03302 }
03303 
03304 
03305 template<typename T, int nDim>
03306 void BoxVorticityFunctional3D<T,nDim>::processBulk (
03307         Box3D domain, TensorField3D<T,nDim>& velocity, TensorField3D<T,nDim>& vorticity )
03308 {
03309     Dot3D offset = computeRelativeDisplacement(velocity, vorticity);
03310     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03311         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03312             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03313                 plint iX2 = iX+offset.x;
03314                 plint iY2 = iY+offset.y;
03315                 plint iZ2 = iZ+offset.z;
03316                 vorticity.get(iX2,iY2,iZ2)[0] =
03317                     fdDataField::bulkVorticityX(velocity, iX,iY,iZ);
03318                 vorticity.get(iX2,iY2,iZ2)[1] = 
03319                     fdDataField::bulkVorticityY(velocity, iX,iY,iZ);
03320                 vorticity.get(iX2,iY2,iZ2)[2] = 
03321                     fdDataField::bulkVorticityZ(velocity, iX,iY,iZ);
03322             }
03323         }
03324     }
03325 }
03326 
03327 template<typename T, int nDim>
03328 void BoxVorticityFunctional3D<T,nDim>::processPlane (
03329         int direction, int orientation, Box3D domain,
03330         TensorField3D<T,nDim>& velocity, TensorField3D<T,nDim>& vorticity )
03331 {
03332     Dot3D offset = computeRelativeDisplacement(velocity, vorticity);
03333     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03334         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03335             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03336                 plint iX2 = iX+offset.x;
03337                 plint iY2 = iY+offset.y;
03338                 plint iZ2 = iZ+offset.z;
03339                 vorticity.get(iX2,iY2,iZ2)[0] = 
03340                     fdDataField::planeVorticityX(velocity,direction,orientation, iX,iY,iZ);
03341                 vorticity.get(iX2,iY2,iZ2)[1] = 
03342                     fdDataField::planeVorticityY(velocity,direction,orientation, iX,iY,iZ);
03343                 vorticity.get(iX2,iY2,iZ2)[2] = 
03344                     fdDataField::planeVorticityZ(velocity,direction,orientation, iX,iY,iZ);
03345             }
03346         }
03347     }
03348 }
03349 
03350 template<typename T, int nDim>
03351 void BoxVorticityFunctional3D<T,nDim>::processEdge (
03352         int plane, int normal1, int normal2, Box3D domain,
03353         TensorField3D<T,nDim>& velocity, TensorField3D<T,nDim>& vorticity )
03354 {
03355     Dot3D offset = computeRelativeDisplacement(velocity, vorticity);
03356     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03357         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03358             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03359                 plint iX2 = iX+offset.x;
03360                 plint iY2 = iY+offset.y;
03361                 plint iZ2 = iZ+offset.z;
03362                 vorticity.get(iX2,iY2,iZ2)[0] = 
03363                     fdDataField::edgeVorticityX(velocity,plane,normal1,normal2, iX,iY,iZ);
03364                 vorticity.get(iX2,iY2,iZ2)[1] = 
03365                     fdDataField::edgeVorticityY(velocity,plane,normal1,normal2, iX,iY,iZ);
03366                 vorticity.get(iX2,iY2,iZ2)[2] = 
03367                     fdDataField::edgeVorticityZ(velocity,plane,normal1,normal2, iX,iY,iZ);
03368             }
03369         }
03370     }
03371 }
03372 
03373 template<typename T, int nDim>
03374 void BoxVorticityFunctional3D<T,nDim>::processCorner (
03375         int normalX, int normalY, int normalZ, Box3D domain,
03376         TensorField3D<T,nDim>& velocity, TensorField3D<T,nDim>& vorticity )
03377 {
03378 
03379     Dot3D offset = computeRelativeDisplacement(velocity, vorticity);
03380     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03381         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03382             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03383                 plint iX2 = iX+offset.x;
03384                 plint iY2 = iY+offset.y;
03385                 plint iZ2 = iZ+offset.z;
03386                 vorticity.get(iX2,iY2,iZ2)[0] = 
03387                     fdDataField::cornerVorticityX(velocity,normalX,normalY,normalZ, iX,iY,iZ);
03388                 vorticity.get(iX2,iY2,iZ2)[1] = 
03389                     fdDataField::cornerVorticityY(velocity,normalX,normalY,normalZ, iX,iY,iZ);
03390                 vorticity.get(iX2,iY2,iZ2)[2] = 
03391                     fdDataField::cornerVorticityZ(velocity,normalX,normalY,normalZ, iX,iY,iZ);
03392             }
03393         }
03394     }
03395 }
03396 
03397 
03398 template<typename T, int nDim>
03399 BoxVorticityFunctional3D<T,nDim>* BoxVorticityFunctional3D<T,nDim>::clone() const
03400 {
03401     return new BoxVorticityFunctional3D<T,nDim>(*this);
03402 }
03403 
03404 template<typename T, int nDim>
03405 void BoxVorticityFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03406     modified[0] = modif::nothing;
03407     modified[1] = modif::staticVariables;
03408 }
03409 
03410 
03411 template<typename T, int nDim>
03412 BlockDomain::DomainT BoxVorticityFunctional3D<T,nDim>::appliesTo() const {
03413     // Don't apply to envelope, because nearest neighbors need to be accessed.
03414     return BlockDomain::bulk;
03415 }
03416 
03417 
03418 template<typename T, int nDim>
03419 void BoxBulkStrainRateFunctional3D<T,nDim>::process (
03420         Box3D domain, TensorField3D<T,nDim>& velocity,
03421                       TensorField3D<T,SymmetricTensorImpl<T,nDim>::n>& S )
03422 {
03423     typedef SymmetricTensorImpl<T,nDim> tensor;
03424     Dot3D offset = computeRelativeDisplacement(velocity, S);
03425     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03426         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03427             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03428                 plint iX2 = iX+offset.x;
03429                 plint iY2 = iY+offset.y;
03430                 plint iZ2 = iZ+offset.z;
03431                 Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2,iZ2);
03432                 el[tensor::xx] = fdDataField::bulkXderiv(velocity, iX, iY, iZ, 0);
03433                 el[tensor::xy] = ( fdDataField::bulkXderiv(velocity, iX, iY, iZ, 1) +
03434                                    fdDataField::bulkYderiv(velocity, iX, iY, iZ, 0) ) / (T)2;
03435                 el[tensor::xz] = ( fdDataField::bulkXderiv(velocity, iX, iY, iZ, 2) +
03436                                    fdDataField::bulkZderiv(velocity, iX, iY, iZ, 0) ) / (T)2;
03437                 el[tensor::yy] = fdDataField::bulkYderiv(velocity, iX, iY, iZ, 1);
03438                 el[tensor::yz] = ( fdDataField::bulkYderiv(velocity, iX, iY, iZ, 2) +
03439                                    fdDataField::bulkZderiv(velocity, iX, iY, iZ, 1) ) / (T)2;
03440                 el[tensor::zz] = fdDataField::bulkZderiv(velocity, iX, iY, iZ, 2);
03441             }
03442         }
03443     }
03444 }
03445 
03446 template<typename T, int nDim>
03447 BoxBulkStrainRateFunctional3D<T,nDim>* BoxBulkStrainRateFunctional3D<T,nDim>::clone() const
03448 {
03449     return new BoxBulkStrainRateFunctional3D<T,nDim>(*this);
03450 }
03451 
03452 template<typename T, int nDim>
03453 void BoxBulkStrainRateFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03454     modified[0] = modif::nothing;
03455     modified[1] = modif::staticVariables;
03456 }
03457 
03458 template<typename T, int nDim>
03459 BlockDomain::DomainT BoxBulkStrainRateFunctional3D<T,nDim>::appliesTo() const {
03460 //     return BlockDomain::bulkAndEnvelope;
03461     return BlockDomain::bulk;
03462 }
03463 
03464 
03465 template<typename T, int nDim>
03466 void BoxStrainRateFunctional3D<T,nDim>::processBulk (
03467         Box3D domain, TensorField3D<T,nDim>& velocity, TensorField3D<T,SymmetricTensorImpl<T,nDim>::n>& S )
03468 {
03469     typedef SymmetricTensorImpl<T,nDim> tensor;
03470     Dot3D offset = computeRelativeDisplacement(velocity, S);
03471     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03472         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03473             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03474                 plint iX2 = iX+offset.x;
03475                 plint iY2 = iY+offset.y;
03476                 plint iZ2 = iZ+offset.z;
03477                 Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2,iZ2);
03478                 el[tensor::xx] = fdDataField::bulkXderiv(velocity, iX, iY, iZ, 0);
03479                 el[tensor::xy] = ( fdDataField::bulkXderiv(velocity, iX, iY, iZ, 1) +
03480                                    fdDataField::bulkYderiv(velocity, iX, iY, iZ, 0) ) / (T)2;
03481                 el[tensor::xz] = ( fdDataField::bulkXderiv(velocity, iX, iY, iZ, 2) +
03482                                    fdDataField::bulkZderiv(velocity, iX, iY, iZ, 0) ) / (T)2;
03483                 el[tensor::yy] = fdDataField::bulkYderiv(velocity, iX, iY, iZ, 1);
03484                 el[tensor::yz] = ( fdDataField::bulkYderiv(velocity, iX, iY, iZ, 2) +
03485                                    fdDataField::bulkZderiv(velocity, iX, iY, iZ, 1) ) / (T)2;
03486                 el[tensor::zz] = fdDataField::bulkZderiv(velocity, iX, iY, iZ, 2);
03487             }
03488         }
03489     }
03490 }
03491 
03492 template<typename T, int nDim>
03493 void BoxStrainRateFunctional3D<T,nDim>::processPlane (
03494         int direction, int orientation, Box3D domain,
03495         TensorField3D<T,nDim>& velocity, TensorField3D<T,SymmetricTensorImpl<T,nDim>::n>& S )
03496 {
03497     typedef SymmetricTensorImpl<T,nDim> tensor;
03498     Dot3D offset = computeRelativeDisplacement(velocity, S);
03499     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03500         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03501             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03502                 plint iX2 = iX+offset.x;
03503                 plint iY2 = iY+offset.y;
03504                 plint iZ2 = iZ+offset.z;
03505                 Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2,iZ2);
03506                 el[tensor::xx] = fdDataField::planeXderiv(velocity, direction,orientation, iX, iY, iZ, 0);
03507                 el[tensor::xy] = ( fdDataField::planeXderiv(velocity, direction,orientation, iX, iY, iZ, 1) +
03508                                fdDataField::planeYderiv(velocity, direction,orientation, iX, iY, iZ, 0) ) / (T)2;
03509                 el[tensor::xz] = ( fdDataField::planeXderiv(velocity, direction,orientation, iX, iY, iZ, 2) +
03510                                fdDataField::planeZderiv(velocity, direction,orientation, iX, iY, iZ, 0) ) / (T)2;
03511                 el[tensor::yy] = fdDataField::planeYderiv(velocity, direction,orientation, iX, iY, iZ, 1);
03512                 el[tensor::yz] = ( fdDataField::planeYderiv(velocity, direction,orientation, iX, iY, iZ, 2) +
03513                                fdDataField::planeZderiv(velocity, direction,orientation, iX, iY, iZ, 1) ) / (T)2;
03514                 el[tensor::zz] = fdDataField::planeZderiv(velocity, direction,orientation, iX, iY, iZ, 2);
03515             }
03516         }
03517     }
03518 }
03519 
03520 template<typename T, int nDim>
03521 void BoxStrainRateFunctional3D<T,nDim>::processEdge (
03522         int plane, int normal1, int normal2, Box3D domain,
03523         TensorField3D<T,nDim>& velocity, TensorField3D<T,SymmetricTensorImpl<T,nDim>::n>& S )
03524 {
03525     typedef SymmetricTensorImpl<T,nDim> tensor;
03526     Dot3D offset = computeRelativeDisplacement(velocity, S);
03527     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03528         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03529             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03530                 plint iX2 = iX+offset.x;
03531                 plint iY2 = iY+offset.y;
03532                 plint iZ2 = iZ+offset.z;
03533                 Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2,iZ2);
03534                 el[tensor::xx] = fdDataField::edgeXderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 0);
03535                 el[tensor::xy] = ( fdDataField::edgeXderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 1) +
03536                                fdDataField::edgeYderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 0) ) / (T)2;
03537                 el[tensor::xz] = ( fdDataField::edgeXderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 2) +
03538                                fdDataField::edgeZderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 0) ) / (T)2;
03539                 el[tensor::yy] = fdDataField::edgeYderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 1);
03540                 el[tensor::yz] = ( fdDataField::edgeYderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 2) +
03541                                fdDataField::edgeZderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 1) ) / (T)2;
03542                 el[tensor::zz] = fdDataField::edgeZderiv(velocity, plane,normal1,normal2, iX, iY, iZ, 2);
03543             }
03544         }
03545     }
03546 }
03547 
03548 template<typename T, int nDim>
03549 void BoxStrainRateFunctional3D<T,nDim>::processCorner (
03550         int normalX, int normalY, int normalZ, Box3D domain,
03551         TensorField3D<T,nDim>& velocity, TensorField3D<T,SymmetricTensorImpl<T,nDim>::n>& S )
03552 {
03553 
03554     typedef SymmetricTensorImpl<T,nDim> tensor;
03555     Dot3D offset = computeRelativeDisplacement(velocity, S);
03556     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03557         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03558             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03559                 plint iX2 = iX+offset.x;
03560                 plint iY2 = iY+offset.y;
03561                 plint iZ2 = iZ+offset.z;
03562                 Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2,iZ2);
03563                 el[tensor::xx] = fdDataField::cornerXderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 0);
03564                 el[tensor::xy] = ( fdDataField::cornerXderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 1) +
03565                                    fdDataField::cornerYderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 0) ) / (T)2;
03566                 el[tensor::xz] = ( fdDataField::cornerXderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 2) +
03567                                    fdDataField::cornerZderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 0) ) / (T)2;
03568                 el[tensor::yy] = fdDataField::cornerYderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 1);
03569                 el[tensor::yz] = ( fdDataField::cornerYderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 2) +
03570                                    fdDataField::cornerZderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 1) ) / (T)2;
03571                 el[tensor::zz] = fdDataField::cornerZderiv(velocity, normalX,normalY,normalZ, iX, iY, iZ, 2);
03572             }
03573         }
03574     }
03575 }
03576 
03577 
03578 template<typename T, int nDim>
03579 BoxStrainRateFunctional3D<T,nDim>* BoxStrainRateFunctional3D<T,nDim>::clone() const
03580 {
03581     return new BoxStrainRateFunctional3D<T,nDim>(*this);
03582 }
03583 
03584 template<typename T, int nDim>
03585 void BoxStrainRateFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03586     modified[0] = modif::nothing;
03587     modified[1] = modif::staticVariables;
03588 }
03589 
03590 template<typename T, int nDim>
03591 BlockDomain::DomainT BoxStrainRateFunctional3D<T,nDim>::appliesTo() const {
03592     // Don't apply to envelope, because nearest neighbors need to be accessed.
03593     return BlockDomain::bulk;
03594 }
03595 
03596 
03597 /* ******** BoxBulkDivergenceFunctional3D ****************************************** */
03598 
03599 template<typename T, int nDim>
03600 void BoxBulkDivergenceFunctional3D<T,nDim>::process (
03601         Box3D domain, ScalarField3D<T>& divergence,
03602                       TensorField3D<T,nDim>& velocity )
03603 {
03604     Dot3D offset = computeRelativeDisplacement(divergence, velocity);
03605     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03606         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03607             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03608                 plint iX2 = iX+offset.x;
03609                 plint iY2 = iY+offset.y;
03610                 plint iZ2 = iZ+offset.z;
03611                 divergence.get(iX,iY,iZ) =
03612                     fdDataField::bulkXderiv(velocity, iX2,iY2,iZ2, 0) +
03613                     fdDataField::bulkYderiv(velocity, iX2,iY2,iZ2, 1) +
03614                     fdDataField::bulkZderiv(velocity, iX2,iY2,iZ2, 2);
03615             }
03616         }
03617     }
03618 }
03619 
03620 template<typename T, int nDim>
03621 BoxBulkDivergenceFunctional3D<T,nDim>* BoxBulkDivergenceFunctional3D<T,nDim>::clone() const
03622 {
03623     return new BoxBulkDivergenceFunctional3D<T,nDim>(*this);
03624 }
03625 
03626 template<typename T, int nDim>
03627 void BoxBulkDivergenceFunctional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03628     modified[0] = modif::staticVariables;   // Divergence.
03629     modified[1] = modif::nothing;  // Velocity.
03630 }
03631 
03632 template<typename T, int nDim>
03633 BlockDomain::DomainT BoxBulkDivergenceFunctional3D<T,nDim>::appliesTo() const {
03634     return BlockDomain::bulk;
03635 }
03636 
03637 
03638 /* ******** Tensor__B_functional3D ****************************************** */
03639 
03640 template<typename T, int nDim>
03641 void Tensor_A_plus_B_functional3D<T,nDim>::process (
03642         Box3D domain, std::vector<TensorField3D<T,nDim>*> fields )
03643 {
03644     PLB_PRECONDITION( fields.size()==3 );
03645     TensorField3D<T,nDim>& A = *fields[0];
03646     TensorField3D<T,nDim>& B = *fields[1];
03647     TensorField3D<T,nDim>& result = *fields[2];
03648     Dot3D offsetB      = computeRelativeDisplacement(A,B);
03649     Dot3D offsetResult = computeRelativeDisplacement(A,result);
03650     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03651         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03652             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03653                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
03654                     = A.get(iX,iY,iZ) + B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
03655             }
03656         }
03657     }
03658 }
03659 
03660 template<typename T, int nDim>
03661 Tensor_A_plus_B_functional3D<T,nDim>* Tensor_A_plus_B_functional3D<T,nDim>::clone() const {
03662     return new Tensor_A_plus_B_functional3D<T,nDim>(*this);
03663 }
03664 
03665 template<typename T, int nDim>
03666 void Tensor_A_plus_B_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03667     modified[0] = modif::nothing;
03668     modified[1] = modif::nothing;
03669     modified[2] = modif::staticVariables;
03670 }
03671 
03672 template<typename T, int nDim>
03673 BlockDomain::DomainT Tensor_A_plus_B_functional3D<T,nDim>::appliesTo() const {
03674     return BlockDomain::bulkAndEnvelope;
03675 }
03676 
03677 
03678 /* ******** Tensor_A_minus_B_functional3D ************************************ */
03679 
03680 template<typename T, int nDim>
03681 void Tensor_A_minus_B_functional3D<T,nDim>::process (
03682         Box3D domain, std::vector<TensorField3D<T,nDim>*> fields )
03683 {
03684     PLB_PRECONDITION( fields.size()==3 );
03685     TensorField3D<T,nDim>& A = *fields[0];
03686     TensorField3D<T,nDim>& B = *fields[1];
03687     TensorField3D<T,nDim>& result = *fields[2];
03688     Dot3D offsetB      = computeRelativeDisplacement(A,B);
03689     Dot3D offsetResult = computeRelativeDisplacement(A,result);
03690     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03691         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03692             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03693                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
03694                     = A.get(iX,iY,iZ) - B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
03695             }
03696         }
03697     }
03698 }
03699 
03700 template<typename T, int nDim>
03701 Tensor_A_minus_B_functional3D<T,nDim>* Tensor_A_minus_B_functional3D<T,nDim>::clone() const {
03702     return new Tensor_A_minus_B_functional3D<T,nDim>(*this);
03703 }
03704 
03705 template<typename T, int nDim>
03706 void Tensor_A_minus_B_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03707     modified[0] = modif::nothing;
03708     modified[1] = modif::nothing;
03709     modified[2] = modif::staticVariables;
03710 }
03711 
03712 template<typename T, int nDim>
03713 BlockDomain::DomainT Tensor_A_minus_B_functional3D<T,nDim>::appliesTo() const {
03714     return BlockDomain::bulkAndEnvelope;
03715 }
03716 
03717 
03718 /* ******** Tensor_A_times_B_functional3D ************************************ */
03719 
03720 template<typename T, int nDim>
03721 void Tensor_A_times_B_functional3D<T,nDim>::process (
03722         Box3D domain, std::vector<TensorField3D<T,nDim>*> fields )
03723 {
03724     PLB_PRECONDITION( fields.size()==3 );
03725     TensorField3D<T,nDim>& A = *fields[0];
03726     TensorField3D<T,nDim>& B = *fields[1];
03727     TensorField3D<T,nDim>& result = *fields[2];
03728     Dot3D offsetB      = computeRelativeDisplacement(A,B);
03729     Dot3D offsetResult = computeRelativeDisplacement(A,result);
03730     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03731         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03732             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03733                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
03734                     = A.get(iX,iY,iZ) * B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
03735             }
03736         }
03737     }
03738 }
03739 
03740 template<typename T, int nDim>
03741 Tensor_A_times_B_functional3D<T,nDim>* Tensor_A_times_B_functional3D<T,nDim>::clone() const {
03742     return new Tensor_A_times_B_functional3D<T,nDim>(*this);
03743 }
03744 
03745 template<typename T, int nDim>
03746 void Tensor_A_times_B_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03747     modified[0] = modif::nothing;
03748     modified[1] = modif::nothing;
03749     modified[2] = modif::staticVariables;
03750 }
03751 
03752 template<typename T, int nDim>
03753 BlockDomain::DomainT Tensor_A_times_B_functional3D<T,nDim>::appliesTo() const {
03754     return BlockDomain::bulkAndEnvelope;
03755 }
03756 
03757 
03758 /* ******** Tensor_A_dividedBy_B_functional3D ************************************ */
03759 
03760 template<typename T, int nDim>
03761 void Tensor_A_dividedBy_B_functional3D<T,nDim>::process (
03762         Box3D domain, std::vector<TensorField3D<T,nDim>*> fields )
03763 {
03764     PLB_PRECONDITION( fields.size()==3 );
03765     TensorField3D<T,nDim>& A = *fields[0];
03766     TensorField3D<T,nDim>& B = *fields[1];
03767     TensorField3D<T,nDim>& result = *fields[2];
03768     Dot3D offsetB      = computeRelativeDisplacement(A,B);
03769     Dot3D offsetResult = computeRelativeDisplacement(A,result);
03770     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03771         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03772             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03773                 result.get(iX+offsetResult.x,iY+offsetResult.y,iZ+offsetResult.z)
03774                     = A.get(iX,iY,iZ) / B.get(iX+offsetB.x,iY+offsetB.y,iZ+offsetB.z);
03775             }
03776         }
03777     }
03778 }
03779 
03780 template<typename T, int nDim>
03781 Tensor_A_dividedBy_B_functional3D<T,nDim>* Tensor_A_dividedBy_B_functional3D<T,nDim>::clone() const {
03782     return new Tensor_A_dividedBy_B_functional3D<T,nDim>(*this);
03783 }
03784 
03785 template<typename T, int nDim>
03786 void Tensor_A_dividedBy_B_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03787     modified[0] = modif::nothing;
03788     modified[1] = modif::nothing;
03789     modified[2] = modif::staticVariables;
03790 }
03791 
03792 template<typename T, int nDim>
03793 BlockDomain::DomainT Tensor_A_dividedBy_B_functional3D<T,nDim>::appliesTo() const {
03794     return BlockDomain::bulkAndEnvelope;
03795 }
03796 
03797 
03798 /* ******** Tensor_A_plus_B_inplace_functional3D ************************************ */
03799 
03800 template<typename T, int nDim>
03801 void Tensor_A_plus_B_inplace_functional3D<T,nDim>::process (
03802         Box3D domain, TensorField3D<T,nDim>& A, TensorField3D<T,nDim>& B)
03803 {
03804     Dot3D offset = computeRelativeDisplacement(A,B);
03805     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03806         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03807             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03808                 A.get(iX,iY,iZ) += B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03809             }
03810         }
03811     }
03812 }
03813 
03814 template<typename T, int nDim>
03815 Tensor_A_plus_B_inplace_functional3D<T,nDim>* Tensor_A_plus_B_inplace_functional3D<T,nDim>::clone() const {
03816     return new Tensor_A_plus_B_inplace_functional3D<T,nDim>(*this);
03817 }
03818 
03819 template<typename T, int nDim>
03820 void Tensor_A_plus_B_inplace_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03821     modified[0] = modif::staticVariables;
03822     modified[1] = modif::nothing;
03823 }
03824 
03825 template<typename T, int nDim>
03826 BlockDomain::DomainT Tensor_A_plus_B_inplace_functional3D<T,nDim>::appliesTo() const {
03827     return BlockDomain::bulkAndEnvelope;
03828 }
03829 
03830 
03831 /* ******** Tensor_A_minus_B_inplace_functional3D ************************************ */
03832 
03833 template<typename T, int nDim>
03834 void Tensor_A_minus_B_inplace_functional3D<T,nDim>::process (
03835         Box3D domain, TensorField3D<T,nDim>& A, TensorField3D<T,nDim>& B)
03836 {
03837     Dot3D offset = computeRelativeDisplacement(A,B);
03838     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03839         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03840             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03841                 A.get(iX,iY,iZ) -= B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03842             }
03843         }
03844     }
03845 }
03846 
03847 template<typename T, int nDim>
03848 Tensor_A_minus_B_inplace_functional3D<T,nDim>* Tensor_A_minus_B_inplace_functional3D<T,nDim>::clone() const {
03849     return new Tensor_A_minus_B_inplace_functional3D<T,nDim>(*this);
03850 }
03851 
03852 template<typename T, int nDim>
03853 void Tensor_A_minus_B_inplace_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03854     modified[0] = modif::staticVariables;
03855     modified[1] = modif::nothing;
03856 }
03857 
03858 template<typename T, int nDim>
03859 BlockDomain::DomainT Tensor_A_minus_B_inplace_functional3D<T,nDim>::appliesTo() const {
03860     return BlockDomain::bulkAndEnvelope;
03861 }
03862 
03863 
03864 /* ******** Tensor_A_times_B_inplace_functional3D ************************************ */
03865 
03866 template<typename T, int nDim>
03867 void Tensor_A_times_B_inplace_functional3D<T,nDim>::process (
03868         Box3D domain, TensorField3D<T,nDim>& A, TensorField3D<T,nDim>& B)
03869 {
03870     Dot3D offset = computeRelativeDisplacement(A,B);
03871     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03872         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03873             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03874                 A.get(iX,iY,iZ) *= B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03875             }
03876         }
03877     }
03878 }
03879 
03880 template<typename T, int nDim>
03881 Tensor_A_times_B_inplace_functional3D<T,nDim>* Tensor_A_times_B_inplace_functional3D<T,nDim>::clone() const {
03882     return new Tensor_A_times_B_inplace_functional3D<T,nDim>(*this);
03883 }
03884 
03885 template<typename T, int nDim>
03886 void Tensor_A_times_B_inplace_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03887     modified[0] = modif::staticVariables;
03888     modified[1] = modif::nothing;
03889 }
03890 
03891 template<typename T, int nDim>
03892 BlockDomain::DomainT Tensor_A_times_B_inplace_functional3D<T,nDim>::appliesTo() const {
03893     return BlockDomain::bulkAndEnvelope;
03894 }
03895 
03896 
03897 /* ******** Tensor_A_times_alpha_inplace_functional3D ************************************ */
03898 
03899 template<typename T, int nDim>
03900 Tensor_A_times_alpha_inplace_functional3D<T,nDim>::
03901     Tensor_A_times_alpha_inplace_functional3D(T alpha_)
03902         : alpha(alpha_)
03903 { }
03904 
03905 template<typename T, int nDim>
03906 void Tensor_A_times_alpha_inplace_functional3D<T,nDim>::process (
03907         Box3D domain, TensorField3D<T,nDim>& A)
03908 {
03909     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03910         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03911             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03912                 A.get(iX,iY,iZ) *= alpha;
03913             }
03914         }
03915     }
03916 }
03917 
03918 template<typename T, int nDim>
03919 Tensor_A_times_alpha_inplace_functional3D<T,nDim>*
03920     Tensor_A_times_alpha_inplace_functional3D<T,nDim>::clone() const
03921 {
03922     return new Tensor_A_times_alpha_inplace_functional3D<T,nDim>(*this);
03923 }
03924 
03925 template<typename T, int nDim>
03926 void Tensor_A_times_alpha_inplace_functional3D<T,nDim>::
03927     getTypeOfModification(std::vector<modif::ModifT>& modified) const
03928 {
03929     modified[0] = modif::staticVariables;
03930 }
03931 
03932 template<typename T, int nDim>
03933 BlockDomain::DomainT Tensor_A_times_alpha_inplace_functional3D<T,nDim>::appliesTo() const {
03934     return BlockDomain::bulkAndEnvelope;
03935 }
03936 
03937 /* ******** Tensor_A_times_alpha_functional3D ************************************ */
03938 
03939 template<typename T, int nDim>
03940 Tensor_A_times_alpha_functional3D<T,nDim>::
03941     Tensor_A_times_alpha_functional3D(T alpha_)
03942         : alpha(alpha_)
03943 { }
03944 
03945 template<typename T, int nDim>
03946 void Tensor_A_times_alpha_functional3D<T,nDim>::process (
03947     Box3D domain, TensorField3D<T,nDim>& A, TensorField3D<T,nDim>& result)
03948 {
03949     Dot3D offset = computeRelativeDisplacement(A, result);
03950     
03951     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03952         plint bX = iX + offset.x;
03953         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03954             plint bY = iY + offset.y;
03955             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03956                 plint bZ = iZ + offset.z;
03957                 result.get(bX,bY,bZ) = alpha*A.get(iX,iY,iZ);
03958             }
03959         }
03960     }
03961 }
03962 
03963 template<typename T, int nDim>
03964 Tensor_A_times_alpha_functional3D<T,nDim>*
03965     Tensor_A_times_alpha_functional3D<T,nDim>::clone() const
03966 {
03967     return new Tensor_A_times_alpha_functional3D<T,nDim>(*this);
03968 }
03969 
03970 template<typename T, int nDim>
03971 void Tensor_A_times_alpha_functional3D<T,nDim>::
03972     getTypeOfModification(std::vector<modif::ModifT>& modified) const
03973 {
03974     modified[0] = modif::nothing;
03975     modified[1] = modif::staticVariables;
03976 }
03977 
03978 template<typename T, int nDim>
03979 BlockDomain::DomainT Tensor_A_times_alpha_functional3D<T,nDim>::appliesTo() const {
03980     return BlockDomain::bulkAndEnvelope;
03981 }
03982 
03983 
03984 /* ******** Tensor_A_dividedBy_B_inplace_functional3D ************************************ */
03985 
03986 template<typename T, int nDim>
03987 void Tensor_A_dividedBy_B_inplace_functional3D<T,nDim>::process (
03988         Box3D domain, TensorField3D<T,nDim>& A, TensorField3D<T,nDim>& B)
03989 {
03990     Dot3D offset = computeRelativeDisplacement(A,B);
03991     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03992         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03993             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
03994                 A.get(iX,iY,iZ) /= B.get(iX+offset.x,iY+offset.y,iZ+offset.z);
03995             }
03996         }
03997     }
03998 }
03999 
04000 template<typename T, int nDim>
04001 Tensor_A_dividedBy_B_inplace_functional3D<T,nDim>* Tensor_A_dividedBy_B_inplace_functional3D<T,nDim>::clone() const {
04002     return new Tensor_A_dividedBy_B_inplace_functional3D<T,nDim>(*this);
04003 }
04004 
04005 template<typename T, int nDim>
04006 void Tensor_A_dividedBy_B_inplace_functional3D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
04007     modified[0] = modif::staticVariables;
04008     modified[1] = modif::nothing;
04009 }
04010 
04011 template<typename T, int nDim>
04012 BlockDomain::DomainT Tensor_A_dividedBy_B_inplace_functional3D<T,nDim>::appliesTo() const {
04013     return BlockDomain::bulkAndEnvelope;
04014 }
04015 
04016 
04017 
04018 /* ************* Class LBMsmoothen3D ******************* */
04019 
04020 template<typename T, template<typename U> class Descriptor>
04021 void LBMsmoothen3D<T,Descriptor>::process (
04022         Box3D domain, ScalarField3D<T>& data, ScalarField3D<T>& result)
04023 {
04024     typedef Descriptor<T> D;
04025     Dot3D offset = computeRelativeDisplacement(data, result);
04026     // Define dimensions of a viscosity.
04027     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
04028         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
04029             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
04030                 result.get(iX+offset.x,iY+offset.y,iZ+offset.z) = (T)0;
04031                 for (plint iPop=0; iPop<D::q; ++iPop) {
04032                     plint nextX = iX+D::c[iPop][0];
04033                     plint nextY = iY+D::c[iPop][1];
04034                     plint nextZ = iZ+D::c[iPop][2];
04035                     result.get(iX+offset.x,iY+offset.y,iZ+offset.z) +=
04036                         D::t[iPop] * data.get(nextX,nextY,nextZ);
04037                 }
04038             }
04039         }
04040     }
04041 }
04042 
04043 template<typename T, template<typename U> class Descriptor>
04044 LBMsmoothen3D<T,Descriptor>*
04045     LBMsmoothen3D<T,Descriptor>::clone() const
04046 {
04047     return new LBMsmoothen3D<T,Descriptor>(*this);
04048 }
04049 
04050 template<typename T, template<typename U> class Descriptor>
04051 BlockDomain::DomainT LBMsmoothen3D<T,Descriptor>::appliesTo() const
04052 {
04053     return BlockDomain::bulk;
04054 }
04055 
04056 template<typename T, template<typename U> class Descriptor>
04057 void LBMsmoothen3D<T,Descriptor>::getTypeOfModification (
04058         std::vector<modif::ModifT>& modified) const
04059 {
04060     modified[0] = modif::nothing;
04061     modified[1] = modif::staticVariables;
04062 }
04063 
04064 }  // namespace plb
04065 
04066 #endif  // DATA_ANALYSIS_FUNCTIONAL_3D_HH