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

dataAnalysisFunctional2D.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_2D_HH
00029 #define DATA_ANALYSIS_FUNCTIONAL_2D_HH
00030 
00031 #include "dataProcessors/dataAnalysisFunctional2D.h"
00032 #include "core/blockStatistics.h"
00033 #include "core/plbDebug.h"
00034 #include "core/util.h"
00035 #include "latticeBoltzmann/momentTemplates.h"
00036 #include "latticeBoltzmann/geometricOperationTemplates.h"
00037 #include "finiteDifference/fdStencils1D.h"
00038 #include "atomicBlock/atomicBlock2D.h"
00039 #include "atomicBlock/blockLattice2D.h"
00040 #include "atomicBlock/dataField2D.h"
00041 #include <cmath>
00042 #include <limits>
00043 
00044 namespace plb {
00045 
00046 /* *************** PART I ******************************************** */
00047 /* *************** Analysis of the block-lattice ********************* */
00048 /* ******************************************************************* */
00049 
00050 /* *************** Reductive Data Functionals for BlockLattice ******* */
00051 
00052 template<typename T, template<typename U> class Descriptor> 
00053 BoxSumRhoBarFunctional2D<T,Descriptor>::BoxSumRhoBarFunctional2D()
00054     : sumRhoBarId(this->getStatistics().subscribeSum())
00055 { }
00056 
00057 template<typename T, template<typename U> class Descriptor> 
00058 void BoxSumRhoBarFunctional2D<T,Descriptor>::process (
00059         Box2D domain, BlockLattice2D<T,Descriptor>& lattice )
00060 {
00061     BlockStatistics& statistics = this->getStatistics();
00062     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00063         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00064             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00065             statistics.gatherSum (
00066                     sumRhoBarId, cell.getDynamics().computeRhoBar(cell)
00067             );
00068         }
00069     }
00070 }
00071 
00072 template<typename T, template<typename U> class Descriptor> 
00073 BoxSumRhoBarFunctional2D<T,Descriptor>*
00074     BoxSumRhoBarFunctional2D<T,Descriptor>::clone() const
00075 {
00076     return new BoxSumRhoBarFunctional2D(*this);
00077 }
00078 
00079 template<typename T, template<typename U> class Descriptor> 
00080 T BoxSumRhoBarFunctional2D<T,Descriptor>::getSumRhoBar() const {
00081     return this->getStatistics().getSum(sumRhoBarId);
00082 }
00083 
00084 
00085 template<typename T, template<typename U> class Descriptor> 
00086 BoxSumEnergyFunctional2D<T,Descriptor>::BoxSumEnergyFunctional2D()
00087     : sumEnergyId(this->getStatistics().subscribeSum())
00088 { }
00089 
00090 template<typename T, template<typename U> class Descriptor> 
00091 void BoxSumEnergyFunctional2D<T,Descriptor>::process (
00092         Box2D domain, BlockLattice2D<T,Descriptor>& lattice )
00093 {
00094     BlockStatistics& statistics = this->getStatistics();
00095     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00096         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00097             Array<T,Descriptor<T>::d> velocity;
00098             lattice.get(iX,iY).computeVelocity(velocity);
00099             T uNormSqr = VectorTemplate<T,Descriptor>::normSqr(velocity);
00100             statistics.gatherSum(sumEnergyId, uNormSqr);
00101         }
00102     }
00103 }
00104 
00105 template<typename T, template<typename U> class Descriptor> 
00106 BoxSumEnergyFunctional2D<T,Descriptor>*
00107     BoxSumEnergyFunctional2D<T,Descriptor>::clone() const
00108 {
00109     return new BoxSumEnergyFunctional2D(*this);
00110 }
00111 
00112 template<typename T, template<typename U> class Descriptor> 
00113 T BoxSumEnergyFunctional2D<T,Descriptor>::getSumEnergy() const {
00114     return this->getStatistics().getSum(sumEnergyId) / (T)2;
00115 }
00116 
00117 template<typename T, template<typename U> class Descriptor> 
00118 void BoxSumEnergyFunctional2D<T,Descriptor>::getDimensionsX(std::vector<int>& dimensions) const
00119 {
00120     dimensions.resize(1);
00121     dimensions[0] = 2;
00122 }
00123 
00124 template<typename T, template<typename U> class Descriptor> 
00125 void BoxSumEnergyFunctional2D<T,Descriptor>::getDimensionsT(std::vector<int>& dimensions) const
00126 {
00127     dimensions.resize(1);
00128     dimensions[0] = -2;
00129 }
00130 
00131 
00132 /* *************** Data Functionals for BlockLattice ***************** */
00133 
00134 template<typename T, template<typename U> class Descriptor> 
00135 void CopyPopulationsFunctional2D<T,Descriptor>::process (
00136         Box2D domain, BlockLattice2D<T,Descriptor>& latticeFrom,
00137                       BlockLattice2D<T,Descriptor>& latticeTo )
00138 {
00139     Dot2D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00140     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00141         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00142             latticeTo.get(iX+offset.x,iY+offset.y).attributeValues(latticeFrom.get(iX,iY));
00143         }
00144     }
00145 }
00146 
00147 template<typename T, template<typename U> class Descriptor> 
00148 CopyPopulationsFunctional2D<T,Descriptor>* CopyPopulationsFunctional2D<T,Descriptor>::clone() const
00149 {
00150     return new CopyPopulationsFunctional2D<T,Descriptor>(*this);
00151 }
00152 
00153 template<typename T, template<typename U> class Descriptor> 
00154 void CopyPopulationsFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00155     modified[0] = modif::nothing;
00156     modified[1] = modif::staticVariables;
00157 }
00158 
00159 
00160 template<typename T1, template<typename U1> class Descriptor1,typename T2, template<typename U2> class Descriptor2>
00161 void CopyConvertPopulationsFunctional2D<T1,Descriptor1,T2,Descriptor2>::process (
00162                                  Box2D domain, BlockLattice2D<T1,Descriptor1>& latticeFrom,
00163                                  BlockLattice2D<T2,Descriptor2>& latticeTo )
00164 {
00165         Dot2D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00166         for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00167                 for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00168                         for (plint ipop=0; ipop < Descriptor1<T1>::q; ++ipop)
00169                         latticeTo.get(iX+offset.x,iY+offset.y)[ipop]=(T2)latticeFrom.get(iX,iY)[ipop];
00170                 }
00171         }
00172 }
00173 
00174 
00175 template<typename T1, template<typename U1> class Descriptor1, typename T2, template<typename U2> class Descriptor2> 
00176 CopyConvertPopulationsFunctional2D<T1,Descriptor1, T2,Descriptor2>* CopyConvertPopulationsFunctional2D<T1,Descriptor1,T2,Descriptor2>::clone() const
00177 {
00178     return new CopyConvertPopulationsFunctional2D<T1,Descriptor1,T2,Descriptor2>(*this);
00179 }
00180 
00181 template<typename T1, template<typename U1> class Descriptor1, typename T2, template<typename U2> class Descriptor2> 
00182 void CopyConvertPopulationsFunctional2D<T1,Descriptor1,T2,Descriptor2>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00183     modified[0] = modif::nothing;
00184     modified[1] = modif::staticVariables;
00185 }
00186 
00187 
00188 template<typename T, template<typename U> class Descriptor> 
00189 void LatticeCopyAllFunctional2D<T,Descriptor>::process (
00190         Box2D domain, BlockLattice2D<T,Descriptor>& latticeFrom,
00191                       BlockLattice2D<T,Descriptor>& latticeTo )
00192 {
00193     std::vector<char> data;
00194     Dot2D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00195     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00196         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00197             Cell<T,Descriptor> const& fromCell = latticeFrom.get(iX,iY);
00198             Cell<T,Descriptor>& toCell = latticeTo.get(iX+offset.x,iY+offset.y);
00199             toCell.attributeValues(fromCell);
00200 
00201             data.clear();
00202             HierarchicSerializer serializer(data, fromCell.getDynamics().getId());
00203             fromCell.getDynamics().serialize(serializer);
00204 
00205             HierarchicUnserializer unSerializer(data, 0);
00206             toCell.getDynamics().unserialize(unSerializer);
00207         }
00208     }
00209 }
00210 
00211 template<typename T, template<typename U> class Descriptor> 
00212 LatticeCopyAllFunctional2D<T,Descriptor>* LatticeCopyAllFunctional2D<T,Descriptor>::clone() const
00213 {
00214     return new LatticeCopyAllFunctional2D<T,Descriptor>(*this);
00215 }
00216 
00217 template<typename T, template<typename U> class Descriptor> 
00218 void LatticeCopyAllFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00219     modified[0] = modif::nothing;
00220     modified[1] = modif::staticVariables;
00221 }
00222 
00223 template<typename T, template<typename U> class Descriptor> 
00224 BlockDomain::DomainT LatticeCopyAllFunctional2D<T,Descriptor>::appliesTo() const {
00225     return BlockDomain::bulkAndEnvelope;
00226 }
00227 
00228 
00229 
00230 template<typename T, template<typename U> class Descriptor> 
00231 void LatticeRegenerateFunctional2D<T,Descriptor>::process (
00232         Box2D domain, BlockLattice2D<T,Descriptor>& latticeFrom,
00233                       BlockLattice2D<T,Descriptor>& latticeTo )
00234 {
00235     Dot2D offset = computeRelativeDisplacement(latticeFrom, latticeTo);
00236     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00237         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00238             latticeTo.get(iX+offset.x,iY+offset.y).attributeValues(latticeFrom.get(iX,iY));
00239             latticeTo.attributeDynamics(iX+offset.x,iY+offset.y,
00240                                        latticeFrom.get(iX,iY).getDynamics().clone());
00241             latticeTo.get(iX+offset.x,iY+offset.y).
00242                 attributeValues(latticeFrom.get(iX,iY));
00243         }
00244     }
00245 }
00246 
00247 template<typename T, template<typename U> class Descriptor> 
00248 LatticeRegenerateFunctional2D<T,Descriptor>* LatticeRegenerateFunctional2D<T,Descriptor>::clone() const
00249 {
00250     return new LatticeRegenerateFunctional2D<T,Descriptor>(*this);
00251 }
00252 
00253 template<typename T, template<typename U> class Descriptor> 
00254 void LatticeRegenerateFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00255     modified[0] = modif::nothing;
00256     // Full dynamics object must be recreated, because this data processor
00257     //   re-attributes a new dynamics and acts on the bulk only.
00258     modified[1] = modif::dataStructure;
00259 }
00260 
00261 template<typename T, template<typename U> class Descriptor> 
00262 void BoxDensityFunctional2D<T,Descriptor>::process (
00263         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00264 {
00265     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00266     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00267         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00268             scalarField.get(iX+offset.x,iY+offset.y)
00269                 = lattice.get(iX,iY).computeDensity();
00270         }
00271     }
00272 }
00273 
00274 template<typename T, template<typename U> class Descriptor> 
00275 BoxDensityFunctional2D<T,Descriptor>* BoxDensityFunctional2D<T,Descriptor>::clone() const
00276 {
00277     return new BoxDensityFunctional2D<T,Descriptor>(*this);
00278 }
00279 
00280 template<typename T, template<typename U> class Descriptor> 
00281 void BoxDensityFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00282     modified[0] = modif::nothing;
00283     modified[1] = modif::staticVariables;
00284 }
00285 
00286 template<typename T, template<typename U> class Descriptor> 
00287 BlockDomain::DomainT BoxDensityFunctional2D<T,Descriptor>::appliesTo() const {
00288     return BlockDomain::bulkAndEnvelope;
00289 }
00290 
00291 
00292 template<typename T, template<typename U> class Descriptor> 
00293 void BoxRhoBarFunctional2D<T,Descriptor>::process (
00294         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00295 {
00296     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00297     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00298         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00299             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00300             scalarField.get(iX+offset.x,iY+offset.y)
00301                 = cell.getDynamics().computeRhoBar(cell);
00302         }
00303     }
00304 }
00305 
00306 template<typename T, template<typename U> class Descriptor> 
00307 BoxRhoBarFunctional2D<T,Descriptor>* BoxRhoBarFunctional2D<T,Descriptor>::clone() const
00308 {
00309     return new BoxRhoBarFunctional2D<T,Descriptor>(*this);
00310 }
00311 
00312 template<typename T, template<typename U> class Descriptor> 
00313 void BoxRhoBarFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00314     modified[0] = modif::nothing;
00315     modified[1] = modif::staticVariables;
00316 }
00317 
00318 template<typename T, template<typename U> class Descriptor> 
00319 BlockDomain::DomainT BoxRhoBarFunctional2D<T,Descriptor>::appliesTo() const {
00320     return BlockDomain::bulkAndEnvelope;
00321 }
00322 
00323 
00324 template<typename T, template<typename U> class Descriptor> 
00325 void BoxRhoBarJfunctional2D<T,Descriptor>::processGenericBlocks (
00326         Box2D domain, std::vector<AtomicBlock2D*> fields )
00327 {
00328     BlockLattice2D<T,Descriptor>& lattice = *dynamic_cast<BlockLattice2D<T,Descriptor>*>(fields[0]);
00329     ScalarField2D<T>& rhoBarField = *dynamic_cast<ScalarField2D<T>*>(fields[1]);
00330     TensorField2D<T,2>& jField = *dynamic_cast<TensorField2D<T,2>*>(fields[2]);
00331     Dot2D offset1 = computeRelativeDisplacement(lattice, rhoBarField);
00332     Dot2D offset2 = computeRelativeDisplacement(lattice, jField);
00333     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00334        for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00335             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00336             momentTemplates<T,Descriptor>::get_rhoBar_j (
00337                     cell,
00338                     rhoBarField.get(iX+offset1.x,iY+offset1.y),
00339                     jField.get(iX+offset2.x,iY+offset2.y) );
00340         }
00341     }
00342 }
00343 
00344 template<typename T, template<typename U> class Descriptor> 
00345 BoxRhoBarJfunctional2D<T,Descriptor>* BoxRhoBarJfunctional2D<T,Descriptor>::clone() const
00346 {
00347     return new BoxRhoBarJfunctional2D<T,Descriptor>(*this);
00348 }
00349 
00350 template<typename T, template<typename U> class Descriptor> 
00351 void BoxRhoBarJfunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00352     modified[0] = modif::nothing;  // lattice
00353     modified[1] = modif::staticVariables;   // rhoBar
00354     modified[2] = modif::staticVariables;   // j
00355 }
00356 
00357 template<typename T, template<typename U> class Descriptor> 
00358 void PackedRhoBarJfunctional2D<T,Descriptor>::process (
00359         Box2D domain, BlockLattice2D<T,Descriptor>& lattice,
00360                       NTensorField2D<T>& rhoBarJField )
00361 {
00362     Dot2D offset = computeRelativeDisplacement(lattice, rhoBarJField);
00363     T rhoBar;
00364     Array<T,2> j;
00365     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00366        for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00367             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00368             momentTemplates<T,Descriptor>::get_rhoBar_j(cell, rhoBar, j);
00369             T* rhoBarJ = rhoBarJField.get(iX+offset.x,iY+offset.y);
00370             *rhoBarJ = rhoBar;
00371             j.to_cArray(rhoBarJ+1);
00372         }
00373     }
00374 }
00375 
00376 template<typename T, template<typename U> class Descriptor> 
00377 PackedRhoBarJfunctional2D<T,Descriptor>* PackedRhoBarJfunctional2D<T,Descriptor>::clone() const
00378 {
00379     return new PackedRhoBarJfunctional2D<T,Descriptor>(*this);
00380 }
00381 
00382 template<typename T, template<typename U> class Descriptor> 
00383 void PackedRhoBarJfunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00384     modified[0] = modif::nothing;  // lattice
00385     modified[1] = modif::staticVariables;   // rhoBarJ
00386 }
00387 
00388 
00389 template<typename T, template<typename U> class Descriptor> 
00390 void BoxKineticEnergyFunctional2D<T,Descriptor>::process (
00391         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00392 {
00393     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00394     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00395         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00396             Array<T,Descriptor<T>::d> velocity;
00397             lattice.get(iX,iY).computeVelocity(velocity);
00398             scalarField.get(iX+offset.x,iY+offset.y)
00399                 = VectorTemplate<T,Descriptor>::normSqr(velocity) / (T)2;
00400         }
00401     }
00402 }
00403 
00404 template<typename T, template<typename U> class Descriptor> 
00405 BoxKineticEnergyFunctional2D<T,Descriptor>* BoxKineticEnergyFunctional2D<T,Descriptor>::clone() const
00406 {
00407     return new BoxKineticEnergyFunctional2D<T,Descriptor>(*this);
00408 }
00409 
00410 template<typename T, template<typename U> class Descriptor> 
00411 void BoxKineticEnergyFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00412     modified[0] = modif::nothing;
00413     modified[1] = modif::staticVariables;
00414 }
00415 
00416 template<typename T, template<typename U> class Descriptor> 
00417 BlockDomain::DomainT BoxKineticEnergyFunctional2D<T,Descriptor>::appliesTo() const {
00418     return BlockDomain::bulkAndEnvelope;
00419 }
00420 
00421 
00422 template<typename T, template<typename U> class Descriptor> 
00423 void BoxVelocityNormFunctional2D<T,Descriptor>::process (
00424         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00425 {
00426     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00427     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00428         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00429             Array<T,Descriptor<T>::d> velocity;
00430             lattice.get(iX,iY).computeVelocity(velocity);
00431             scalarField.get(iX+offset.x,iY+offset.y)
00432                 = sqrt( VectorTemplate<T,Descriptor>::normSqr(velocity) );
00433         }
00434     }
00435 }
00436 
00437 template<typename T, template<typename U> class Descriptor> 
00438 BoxVelocityNormFunctional2D<T,Descriptor>* BoxVelocityNormFunctional2D<T,Descriptor>::clone() const
00439 {
00440     return new BoxVelocityNormFunctional2D<T,Descriptor>(*this);
00441 }
00442 
00443 template<typename T, template<typename U> class Descriptor> 
00444 void BoxVelocityNormFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00445     modified[0] = modif::nothing;
00446     modified[1] = modif::staticVariables;
00447 }
00448 
00449 template<typename T, template<typename U> class Descriptor> 
00450 BlockDomain::DomainT BoxVelocityNormFunctional2D<T,Descriptor>::appliesTo() const {
00451     return BlockDomain::bulkAndEnvelope;
00452 }
00453 
00454 
00455 
00456 template<typename T, template<typename U> class Descriptor> 
00457 BoxVelocityComponentFunctional2D<T,Descriptor>::BoxVelocityComponentFunctional2D(int iComponent_)
00458     : iComponent(iComponent_)
00459 { }
00460 
00461 template<typename T, template<typename U> class Descriptor> 
00462 void BoxVelocityComponentFunctional2D<T,Descriptor>::process (
00463         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00464 {
00465     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00466     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00467         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00468             Array<T,Descriptor<T>::d> velocity;
00469             lattice.get(iX,iY).computeVelocity(velocity);
00470             scalarField.get(iX+offset.x,iY+offset.y) = velocity[iComponent];
00471         }
00472     }
00473 }
00474 
00475 template<typename T, template<typename U> class Descriptor> 
00476 BoxVelocityComponentFunctional2D<T,Descriptor>* BoxVelocityComponentFunctional2D<T,Descriptor>::clone() const
00477 {
00478     return new BoxVelocityComponentFunctional2D<T,Descriptor>(*this);
00479 }
00480 
00481 template<typename T, template<typename U> class Descriptor> 
00482 void BoxVelocityComponentFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00483     modified[0] = modif::nothing;
00484     modified[1] = modif::staticVariables;
00485 }
00486 
00487 template<typename T, template<typename U> class Descriptor> 
00488 BlockDomain::DomainT BoxVelocityComponentFunctional2D<T,Descriptor>::appliesTo() const {
00489     return BlockDomain::bulkAndEnvelope;
00490 }
00491 
00492 
00493 template<typename T, template<typename U> class Descriptor> 
00494 void BoxVelocityFunctional2D<T,Descriptor>::process (
00495         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, TensorField2D<T,Descriptor<T>::d>& tensorField)
00496 {
00497     Dot2D offset = computeRelativeDisplacement(lattice, tensorField);
00498     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00499         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00500             lattice.get(iX,iY).computeVelocity(tensorField.get(iX+offset.x,iY+offset.y));
00501         }
00502     }
00503 }
00504 
00505 template<typename T, template<typename U> class Descriptor> 
00506 BoxVelocityFunctional2D<T,Descriptor>* BoxVelocityFunctional2D<T,Descriptor>::clone() const
00507 {
00508     return new BoxVelocityFunctional2D<T,Descriptor>(*this);
00509 }
00510 
00511 template<typename T, template<typename U> class Descriptor> 
00512 void BoxVelocityFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00513     modified[0] = modif::nothing;
00514     modified[1] = modif::staticVariables;
00515 }
00516 
00517 template<typename T, template<typename U> class Descriptor> 
00518 BlockDomain::DomainT BoxVelocityFunctional2D<T,Descriptor>::appliesTo() const {
00519     return BlockDomain::bulkAndEnvelope;
00520 }
00521 
00522 
00523 template<typename T, template<typename U> class Descriptor> 
00524 void BoxDeviatoricStressFunctional2D<T,Descriptor>::process (
00525         Box2D domain, BlockLattice2D<T,Descriptor>& lattice,
00526         TensorField2D<T,SymmetricTensor<T,Descriptor>::n>& PiNeq )
00527 {
00528     Dot2D offset = computeRelativeDisplacement(lattice, PiNeq);
00529     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00530         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00531             lattice.get(iX,iY).computeDeviatoricStress(PiNeq.get(iX+offset.x,iY+offset.y));
00532         }
00533     }
00534 }
00535 
00536 template<typename T, template<typename U> class Descriptor> 
00537 BoxDeviatoricStressFunctional2D<T,Descriptor>* BoxDeviatoricStressFunctional2D<T,Descriptor>::clone() const
00538 {
00539     return new BoxDeviatoricStressFunctional2D<T,Descriptor>(*this);
00540 }
00541 
00542 template<typename T, template<typename U> class Descriptor> 
00543 void BoxDeviatoricStressFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00544     modified[0] = modif::nothing;
00545     modified[1] = modif::staticVariables;
00546 }
00547 
00548 template<typename T, template<typename U> class Descriptor> 
00549 BlockDomain::DomainT BoxDeviatoricStressFunctional2D<T,Descriptor>::appliesTo() const {
00550     return BlockDomain::bulkAndEnvelope;
00551 }
00552 
00553 
00554 template<typename T, template<typename U> class Descriptor> 
00555 void BoxStrainRateFromStressFunctional2D<T,Descriptor>::process (
00556         Box2D domain, BlockLattice2D<T,Descriptor>& lattice,
00557         TensorField2D<T,SymmetricTensor<T,Descriptor>::n>& S )
00558 {
00559     Dot2D offset = computeRelativeDisplacement(lattice, S);
00560     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00561         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00562             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00563             Array<T,SymmetricTensor<T,Descriptor>::n>& element = S.get(iX+offset.x,iY+offset.y);
00564             cell.computeDeviatoricStress(element);
00565             T omega     = cell.getDynamics().getOmega();
00566             T rhoBar    = cell.getDynamics().computeRhoBar(cell);
00567             T prefactor = - omega * Descriptor<T>::invCs2 *
00568                             Descriptor<T>::invRho(rhoBar) / (T)2;
00569             for (int iTensor=0; iTensor<SymmetricTensor<T,Descriptor>::n; ++iTensor) {
00570                 element[iTensor] *= prefactor;
00571             }
00572         }
00573     }
00574 }
00575 
00576 template<typename T, template<typename U> class Descriptor> 
00577 BoxStrainRateFromStressFunctional2D<T,Descriptor>* BoxStrainRateFromStressFunctional2D<T,Descriptor>::clone() const
00578 {
00579     return new BoxStrainRateFromStressFunctional2D<T,Descriptor>(*this);
00580 }
00581 
00582 template<typename T, template<typename U> class Descriptor> 
00583 void BoxStrainRateFromStressFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00584     modified[0] = modif::nothing;
00585     modified[1] = modif::staticVariables;
00586 }
00587 
00588 template<typename T, template<typename U> class Descriptor> 
00589 BlockDomain::DomainT BoxStrainRateFromStressFunctional2D<T,Descriptor>::appliesTo() const {
00590     return BlockDomain::bulkAndEnvelope;
00591 }
00592 
00593 template<typename T, template<typename U> class Descriptor> 
00594 void BoxTemperatureFunctional2D<T,Descriptor>::process (
00595         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00596 {
00597     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00598     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00599         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00600             scalarField.get(iX+offset.x,iY+offset.y)
00601                 = lattice.get(iX,iY).computeTemperature();
00602         }
00603     }
00604 }
00605 
00606 template<typename T, template<typename U> class Descriptor> 
00607 BoxTemperatureFunctional2D<T,Descriptor>* BoxTemperatureFunctional2D<T,Descriptor>::clone() const
00608 {
00609     return new BoxTemperatureFunctional2D<T,Descriptor>(*this);
00610 }
00611 
00612 template<typename T, template<typename U> class Descriptor> 
00613 void BoxTemperatureFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00614     modified[0] = modif::nothing;
00615     modified[1] = modif::staticVariables;
00616 }
00617 
00618 template<typename T, template<typename U> class Descriptor> 
00619 BlockDomain::DomainT BoxTemperatureFunctional2D<T,Descriptor>::appliesTo() const {
00620     return BlockDomain::bulkAndEnvelope;
00621 }
00622 
00623 template<typename T, template<typename U> class Descriptor> 
00624 void BoxSoundSpeedFunctional2D<T,Descriptor>::process (
00625         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00626 {
00627     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00628     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00629         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00630             scalarField.get(iX+offset.x,iY+offset.y)
00631                 = sqrt(lattice.get(iX,iY).computeTemperature()*Descriptor<T>::invCs2);
00632                 // the speed of sound for a perfect gas is given by :
00633                 // c = sqrt(gamma*p/rho) = sqrt(gamma*c_l^2*theta)=sqrt(theta/c_l^2)
00634                 // => gamma = 1/cl^4
00635         }
00636     }
00637 }
00638 
00639 template<typename T, template<typename U> class Descriptor> 
00640 BoxSoundSpeedFunctional2D<T,Descriptor>* BoxSoundSpeedFunctional2D<T,Descriptor>::clone() const
00641 {
00642     return new BoxSoundSpeedFunctional2D<T,Descriptor>(*this);
00643 }
00644 
00645 template<typename T, template<typename U> class Descriptor> 
00646 void BoxSoundSpeedFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00647     modified[0] = modif::nothing;
00648     modified[1] = modif::staticVariables;
00649 }
00650 
00651 template<typename T, template<typename U> class Descriptor> 
00652 BlockDomain::DomainT BoxSoundSpeedFunctional2D<T,Descriptor>::appliesTo() const {
00653     return BlockDomain::bulkAndEnvelope;
00654 }
00655 
00656 
00657 template<typename T, template<typename U> class Descriptor> 
00658 BoxPopulationFunctional2D<T,Descriptor>::BoxPopulationFunctional2D(plint iComponent_)
00659     : iComponent(iComponent_)
00660 { }
00661 
00662 template<typename T, template<typename U> class Descriptor> 
00663 void BoxPopulationFunctional2D<T,Descriptor>::process (
00664         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00665 {
00666     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00667     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00668         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00669             scalarField.get(iX+offset.x,iY+offset.y) = lattice.get(iX,iY)[iComponent];
00670         }
00671     }
00672 }
00673 
00674 template<typename T, template<typename U> class Descriptor> 
00675 BoxPopulationFunctional2D<T,Descriptor>* BoxPopulationFunctional2D<T,Descriptor>::clone() const
00676 {
00677     return new BoxPopulationFunctional2D<T,Descriptor>(*this);
00678 }
00679 
00680 template<typename T, template<typename U> class Descriptor> 
00681 void BoxPopulationFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00682     modified[0] = modif::nothing;
00683     modified[1] = modif::staticVariables;
00684 }
00685 
00686 template<typename T, template<typename U> class Descriptor> 
00687 BlockDomain::DomainT BoxPopulationFunctional2D<T,Descriptor>::appliesTo() const {
00688     return BlockDomain::bulkAndEnvelope;
00689 }
00690 
00691 
00692 template<typename T, template<typename U> class Descriptor> 
00693 BoxEquilibriumFunctional2D<T,Descriptor>::BoxEquilibriumFunctional2D(plint iComponent_)
00694     : iComponent(iComponent_)
00695 { }
00696 
00697 template<typename T, template<typename U> class Descriptor> 
00698 void BoxEquilibriumFunctional2D<T,Descriptor>::process (
00699         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& equilibrium)
00700 {
00701     Dot2D offset = computeRelativeDisplacement(lattice, equilibrium);
00702     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00703         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00704             T rhoBar;
00705             Array<T,Descriptor<T>::d> j;
00706             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00707             cell.getDynamics().computeRhoBarJ(cell, rhoBar, j);
00708             T jSqr = normSqr(j);
00709             equilibrium.get(iX+offset.x,iY+offset.y) = cell.computeEquilibrium(iComponent, rhoBar, j, jSqr);
00710         }
00711     }
00712 }
00713 
00714 template<typename T, template<typename U> class Descriptor> 
00715 BoxEquilibriumFunctional2D<T,Descriptor>* BoxEquilibriumFunctional2D<T,Descriptor>::clone() const
00716 {
00717     return new BoxEquilibriumFunctional2D<T,Descriptor>(*this);
00718 }
00719 
00720 template<typename T, template<typename U> class Descriptor> 
00721 void BoxEquilibriumFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00722     modified[0] = modif::nothing;
00723     modified[1] = modif::staticVariables;
00724 }
00725 
00726 template<typename T, template<typename U> class Descriptor> 
00727 BlockDomain::DomainT BoxEquilibriumFunctional2D<T,Descriptor>::appliesTo() const {
00728     return BlockDomain::bulkAndEnvelope;
00729 }
00730 
00731 
00732 template<typename T, template<typename U> class Descriptor> 
00733 BoxAllPopulationsFunctional2D<T,Descriptor>::BoxAllPopulationsFunctional2D()
00734 { }
00735 
00736 template<typename T, template<typename U> class Descriptor> 
00737 void BoxAllPopulationsFunctional2D<T,Descriptor>::process (
00738         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, TensorField2D<T,Descriptor<T>::q>& tensorField)
00739 {
00740     Dot2D offset = computeRelativeDisplacement(lattice, tensorField);
00741     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00742         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00743             for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop) {
00744                 tensorField.get(iX+offset.x,iY+offset.y)[iPop] = lattice.get(iX,iY)[iPop];
00745             }
00746         }
00747     }
00748 }
00749 
00750 template<typename T, template<typename U> class Descriptor> 
00751 BoxAllPopulationsFunctional2D<T,Descriptor>* BoxAllPopulationsFunctional2D<T,Descriptor>::clone() const
00752 {
00753     return new BoxAllPopulationsFunctional2D<T,Descriptor>(*this);
00754 }
00755 
00756 template<typename T, template<typename U> class Descriptor> 
00757 void BoxAllPopulationsFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00758     modified[0] = modif::nothing;
00759     modified[1] = modif::staticVariables;
00760 }
00761 
00762 template<typename T, template<typename U> class Descriptor> 
00763 BlockDomain::DomainT BoxAllPopulationsFunctional2D<T,Descriptor>::appliesTo() const {
00764     return BlockDomain::bulkAndEnvelope;
00765 }
00766 
00767 template<typename T, template<typename U> class Descriptor>
00768 BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>::BoxAllPopulationsToLatticeFunctional2D()
00769 { }
00770 
00771 template<typename T, template<typename U> class Descriptor>
00772 void BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>::process (
00773         Box2D domain, BlockLattice2D<T,Descriptor>& lattice, TensorField2D<T,Descriptor<T>::q>& tensorField)
00774 {
00775     Dot2D offset = computeRelativeDisplacement(lattice, tensorField);
00776     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00777         plint oX = iX + offset.x;
00778         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00779             for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop) {
00780                 lattice.get(iX,iY)[iPop] = tensorField.get(oX,iY+offset.y)[iPop];
00781             }
00782         }
00783     }
00784 }
00785 
00786 template<typename T, template<typename U> class Descriptor>
00787 BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>* BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>::clone() const
00788 {
00789     return new BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>(*this);
00790 }
00791 
00792 template<typename T, template<typename U> class Descriptor>
00793 void BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00794     modified[0] = modif::staticVariables;
00795     modified[1] = modif::nothing;
00796 }
00797     
00798 
00799 template<typename T, template<typename U> class Descriptor>
00800 BlockDomain::DomainT BoxAllPopulationsToLatticeFunctional2D<T,Descriptor>::appliesTo() const {
00801     return BlockDomain::bulkAndEnvelope;
00802 }
00803 
00804 template<typename T, template<typename U> class Descriptor> 
00805 void BoxOmegaFunctional2D<T,Descriptor>::process (
00806     Box2D domain, BlockLattice2D<T,Descriptor>& lattice, ScalarField2D<T>& scalarField)
00807 {
00808     Dot2D offset = computeRelativeDisplacement(lattice, scalarField);
00809     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00810         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00811             Cell<T,Descriptor> const& cell = lattice.get(iX,iY);
00812             scalarField.get(iX+offset.x,iY+offset.y) = cell.getDynamics().getOmega();
00813         }
00814     }
00815 }
00816 
00817 template<typename T, template<typename U> class Descriptor> 
00818 BoxOmegaFunctional2D<T,Descriptor>* BoxOmegaFunctional2D<T,Descriptor>::clone() const
00819 {
00820     return new BoxOmegaFunctional2D<T,Descriptor>(*this);
00821 }
00822 
00823 template<typename T, template<typename U> class Descriptor> 
00824 void BoxOmegaFunctional2D<T,Descriptor>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00825     modified[0] = modif::nothing;
00826     modified[1] = modif::staticVariables;
00827 }
00828 
00829 template<typename T, template<typename U> class Descriptor> 
00830 BlockDomain::DomainT BoxOmegaFunctional2D<T,Descriptor>::appliesTo() const {
00831     return BlockDomain::bulkAndEnvelope;
00832 }
00833 
00834 /* *************** PART II ******************************************* */
00835 /* *************** Analysis of the scalar-field ********************** */
00836 /* ******************************************************************* */
00837 
00839 namespace fdDataField {
00840 
00841 template<typename T>
00842 inline T bulkXderiv (
00843         ScalarField2D<T> const& field, plint iX, plint iY )
00844 {
00845     T dxu = fd::ctl_diff( field.get(iX+1,iY),
00846                           field.get(iX-1,iY) );
00847     return dxu;
00848 }
00849 
00850 template<typename T>
00851 inline T bulkYderiv (
00852         ScalarField2D<T> const& field, plint iX, plint iY )
00853 {
00854     T dyu = fd::ctl_diff( field.get(iX,iY+1),
00855                           field.get(iX,iY-1) );
00856     return dyu;
00857 }
00858 
00859 template<typename T>
00860 inline T edgeXderiv (
00861         ScalarField2D<T> const& field, int direction, int orientation,
00862         plint iX, plint iY )
00863 {
00864     if (direction==0) {
00865         return -orientation *
00866             fd::o1_fwd_diff( field.get(iX              ,iY),
00867                              field.get(iX-1*orientation,iY) );
00868     }
00869     else {
00870         return bulkXderiv(field, iX,iY);
00871     }
00872 }
00873 
00874 template<typename T>
00875 inline T edgeYderiv (
00876         ScalarField2D<T> const& field, int direction, int orientation,
00877         plint iX, plint iY )
00878 {
00879     if (direction==1) {
00880         return -orientation *
00881             fd::o1_fwd_diff( field.get(iX,iY              ),
00882                               field.get(iX,iY-1*orientation) );
00883     }
00884     else {
00885         return bulkYderiv(field, iX,iY);
00886     }
00887 }
00888 
00889 template<typename T>
00890 inline T cornerXderiv (
00891         ScalarField2D<T> const& field,
00892         int normalX, int normalY,
00893         plint iX, plint iY )
00894 {
00895     int orientation = normalX;
00896     return -orientation *
00897         fd::o1_fwd_diff( field.get(iX              ,iY),
00898                          field.get(iX-1*orientation,iY) );
00899 }
00900 
00901 template<typename T>
00902 inline T cornerYderiv (
00903         ScalarField2D<T> const& field,
00904         int normalX, int normalY,
00905         plint iX, plint iY )
00906 {
00907     int orientation = normalY;
00908     return -orientation *
00909         fd::o1_fwd_diff( field.get(iX,iY              ),
00910                          field.get(iX,iY-1*orientation) );
00911 }
00912 
00913 }  // fdDataField
00914 
00915 /* *************** Reductive Data Functionals for ScalarField ******** */
00916 
00917 template<typename T>
00918 BoxScalarSumFunctional2D<T>::BoxScalarSumFunctional2D()
00919     : sumScalarId(this->getStatistics().subscribeSum())
00920 { }
00921 
00922 template<typename T>
00923 void BoxScalarSumFunctional2D<T>::process (
00924         Box2D domain, ScalarField2D<T>& scalarField )
00925 {
00926     BlockStatistics& statistics = this->getStatistics();
00927     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00928         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00929             statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY));
00930         }
00931     }
00932 }
00933 
00934 template<typename T>
00935 BoxScalarSumFunctional2D<T>* BoxScalarSumFunctional2D<T>::clone() const
00936 {
00937     return new BoxScalarSumFunctional2D<T>(*this);
00938 }
00939 
00940 template<typename T>
00941 T BoxScalarSumFunctional2D<T>::getSumScalar() const {
00942     double doubleSum = this->getStatistics().getSum(sumScalarId);
00943     // The sum is internally computed on floating-point values. If T is
00944     //   integer, the value must be rounded at the end.
00945     if (std::numeric_limits<T>::is_integer) {
00946         return (T) util::roundToInt(doubleSum);
00947     }
00948     return (T) doubleSum;
00949 }
00950 
00951 
00952 template<typename T>
00953 MaskedBoxScalarAverageFunctional2D<T>::MaskedBoxScalarAverageFunctional2D(int flag_)
00954     : averageScalarId(this->getStatistics().subscribeAverage()),
00955       flag(flag_)
00956 { }
00957 
00958 template<typename T>
00959 void MaskedBoxScalarAverageFunctional2D<T>::process (
00960         Box2D domain,
00961         ScalarField2D<T>& scalarField,
00962         ScalarField2D<int>& mask )
00963 {
00964     Dot2D offset = computeRelativeDisplacement(scalarField, mask);
00965     BlockStatistics& statistics = this->getStatistics();
00966     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00967         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00968             if (mask.get(iX+offset.x, iY+offset.y)==flag) {
00969                 statistics.gatherAverage(averageScalarId, (double)scalarField.get(iX,iY));
00970                 statistics.incrementStats();
00971             }
00972         }
00973     }
00974 }
00975 
00976 template<typename T>
00977 MaskedBoxScalarAverageFunctional2D<T>* MaskedBoxScalarAverageFunctional2D<T>::clone() const
00978 {
00979     return new MaskedBoxScalarAverageFunctional2D<T>(*this);
00980 }
00981 
00982 template<typename T>
00983 T MaskedBoxScalarAverageFunctional2D<T>::getAverageScalar() const {
00984     double doubleAverage = this->getStatistics().getAverage(averageScalarId);
00985     // The average is internally computed on floating-point values. If T is
00986     //   integer, the value must be rounded at the end.
00987     if (std::numeric_limits<T>::is_integer) {
00988         return (T) util::roundToInt(doubleAverage);
00989     }
00990     return (T) doubleAverage;
00991 }
00992 
00993 
00994 template<typename T>
00995 BoxScalarMinFunctional2D<T>::BoxScalarMinFunctional2D()
00996     : maxScalarId(this->getStatistics().subscribeMax())
00997 { }
00998 
00999 template<typename T>
01000 void BoxScalarMinFunctional2D<T>::process (
01001         Box2D domain, ScalarField2D<T>& scalarField )
01002 {
01003     BlockStatistics& statistics = this->getStatistics();
01004     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01005         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01006             // BlockStatistics computes only maximum, no minimum. Therefore,
01007             //   the relation min(x) = -max(-x) is used.
01008             statistics.gatherMax(maxScalarId, -(double)scalarField.get(iX,iY));
01009         }
01010     }
01011 }
01012 
01013 template<typename T>
01014 BoxScalarMinFunctional2D<T>* BoxScalarMinFunctional2D<T>::clone() const
01015 {
01016     return new BoxScalarMinFunctional2D<T>(*this);
01017 }
01018 
01019 template<typename T>
01020 T BoxScalarMinFunctional2D<T>::getMinScalar() const {
01021     // The minus sign accounts for the relation min(x) = -max(-x).
01022     // The sum is internally computed on floating-point values. If T is
01023     //   integer, the value must be rounded at the end.
01024     double doubleMin = - this->getStatistics().getMax(maxScalarId);
01025     if (std::numeric_limits<T>::is_integer) {
01026         return (T) util::roundToInt(doubleMin);
01027     }
01028     return (T) doubleMin;
01029 }
01030 
01031 
01032 template<typename T>
01033 BoxScalarMaxFunctional2D<T>::BoxScalarMaxFunctional2D()
01034     : maxScalarId(this->getStatistics().subscribeMax())
01035 { }
01036 
01037 template<typename T>
01038 void BoxScalarMaxFunctional2D<T>::process (
01039         Box2D domain, ScalarField2D<T>& scalarField )
01040 {
01041     BlockStatistics& statistics = this->getStatistics();
01042     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01043         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01044             statistics.gatherMax(maxScalarId, (double)scalarField.get(iX,iY));
01045         }
01046     }
01047 }
01048 
01049 template<typename T>
01050 BoxScalarMaxFunctional2D<T>* BoxScalarMaxFunctional2D<T>::clone() const
01051 {
01052     return new BoxScalarMaxFunctional2D<T>(*this);
01053 }
01054 
01055 template<typename T>
01056 T BoxScalarMaxFunctional2D<T>::getMaxScalar() const {
01057     // The sum is internally computed on floating-point values. If T is
01058     //   integer, the value must be rounded at the end.
01059     double doubleMax = this->getStatistics().getMax(maxScalarId);
01060     if (std::numeric_limits<T>::is_integer) {
01061         return (T) util::roundToInt(doubleMax);
01062     }
01063     return (T) doubleMax;
01064 }
01065 
01066 
01067 template<typename T>
01068 BoundedBoxScalarSumFunctional2D<T>::BoundedBoxScalarSumFunctional2D()
01069     : sumScalarId(this->getStatistics().subscribeSum())
01070 { }
01071 
01072 template<typename T>
01073 void BoundedBoxScalarSumFunctional2D<T>::processBulk (
01074         Box2D domain, ScalarField2D<T>& scalarField )
01075 {
01076     BlockStatistics& statistics = this->getStatistics();
01077     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01078         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01079             statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY));
01080         }
01081     }
01082 }
01083 
01084 template<typename T>
01085 void BoundedBoxScalarSumFunctional2D<T>::processEdge (
01086         int direction, int orientation,
01087         Box2D domain, ScalarField2D<T>& scalarField )
01088 {
01089     BlockStatistics& statistics = this->getStatistics();
01090     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01091         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01092             // Edge nodes have a weight of 0.5, because only 50% of the
01093             //   cell centered at the node is inside the computational domain.
01094             statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY) / 2.);
01095         }
01096     }
01097 }
01098 
01099 template<typename T>
01100 void BoundedBoxScalarSumFunctional2D<T>::processCorner (
01101         int normalX, int normalY,
01102         Box2D domain, ScalarField2D<T>& scalarField )
01103 {
01104     BlockStatistics& statistics = this->getStatistics();
01105     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01106         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01107             // Corner nodes have a weight of 0.25, because only 25% of the
01108             //   cell centered at the node is inside the computational domain.
01109             statistics.gatherSum(sumScalarId, (double)scalarField.get(iX,iY) / 4.);
01110         }
01111     }
01112 }
01113 
01114 template<typename T>
01115 BoundedBoxScalarSumFunctional2D<T>* BoundedBoxScalarSumFunctional2D<T>::clone() const
01116 {
01117     return new BoundedBoxScalarSumFunctional2D<T>(*this);
01118 }
01119 
01120 template<typename T>
01121 T BoundedBoxScalarSumFunctional2D<T>::getSumScalar() const {
01122     double doubleSum = this->getStatistics().getSum(sumScalarId);
01123     // The sum is internally computed on floating-point values. If T is
01124     //   integer, the value must be rounded at the end.
01125     if (std::numeric_limits<T>::is_integer) {
01126         return (T) util::roundToInt(doubleSum);
01127     }
01128     return (T) doubleSum;
01129 }
01130 
01131 
01132 
01133 template<typename T1, typename T2>
01134 void CopyConvertScalarFunctional2D<T1,T2>::process (
01135         Box2D domain, ScalarField2D<T1>& field1,
01136                       ScalarField2D<T2>& field2 )
01137 {
01138     Dot2D offset = computeRelativeDisplacement(field1, field2);
01139 
01140     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01141         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01142             field2.get(iX+offset.x,iY+offset.y) =
01143                 (T2) field1.get(iX,iY);
01144         }
01145     }
01146 }
01147 
01148 template<typename T1, typename T2>
01149 CopyConvertScalarFunctional2D<T1,T2>* CopyConvertScalarFunctional2D<T1,T2>::clone() const
01150 {
01151     return new CopyConvertScalarFunctional2D<T1,T2>(*this);
01152 }
01153 
01154 template<typename T1, typename T2>
01155 void CopyConvertScalarFunctional2D<T1,T2>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01156     modified[0] = modif::nothing;
01157     modified[1] = modif::staticVariables;
01158 }
01159 
01160 template<typename T1, typename T2>
01161 BlockDomain::DomainT CopyConvertScalarFunctional2D<T1,T2>::appliesTo() const {
01162     return BlockDomain::bulk;
01163 }
01164 
01165 
01166 
01167 /* *************** Data Functionals for scalar-fields **************** */
01168 
01169 template<typename T>
01170 void ExtractScalarSubDomainFunctional2D<T>::process (
01171         Box2D domain, ScalarField2D<T>& field1,
01172                       ScalarField2D<T>& field2 )
01173 {
01174     Dot2D offset = computeRelativeDisplacement(field1, field2);
01175     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01176         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01177             field2.get(iX+offset.x,iY+offset.y) = field1.get(iX,iY);
01178         }
01179     }
01180 }
01181 
01182 template<typename T>
01183 ExtractScalarSubDomainFunctional2D<T>* ExtractScalarSubDomainFunctional2D<T>::clone() const
01184 {
01185     return new ExtractScalarSubDomainFunctional2D<T>(*this);
01186 }
01187 
01188 template<typename T>
01189 void ExtractScalarSubDomainFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01190     modified[0] = modif::nothing;
01191     modified[1] = modif::staticVariables;
01192 }
01193 
01194 template<typename T>
01195 BlockDomain::DomainT ExtractScalarSubDomainFunctional2D<T>::appliesTo() const {
01196     return BlockDomain::bulkAndEnvelope;
01197 }
01198 
01199 /* ******** compute absolute value functional 2D ************************************* */
01200 
01201 template<typename T>
01202 void ComputeAbsoluteValueFunctional2D<T>::process (
01203         Box2D domain, ScalarField2D<T>& A,
01204                       ScalarField2D<T>& B )
01205 {
01206     Dot2D offset = computeRelativeDisplacement(A, B);
01207     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01208         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01209             B.get(iX+offset.x,iY+offset.y) = fabs(A.get(iX,iY));
01210         }
01211     }
01212 }
01213 
01214 template<typename T>
01215 ComputeAbsoluteValueFunctional2D<T>* ComputeAbsoluteValueFunctional2D<T>::clone() const
01216 {
01217     return new ComputeAbsoluteValueFunctional2D<T>(*this);
01218 }
01219 
01220 template<typename T>
01221 void ComputeAbsoluteValueFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01222     modified[0] = modif::nothing;
01223     modified[1] = modif::staticVariables;
01224 }
01225 
01226 template<typename T>
01227 BlockDomain::DomainT ComputeAbsoluteValueFunctional2D<T>::appliesTo() const {
01228     return BlockDomain::bulkAndEnvelope;
01229 }
01230 
01231 /* ******** compute sqrt functional 2D ************************************* */
01232 
01233 template<typename T>
01234 void ComputeScalarSqrtFunctional2D<T>::process (
01235         Box2D domain, ScalarField2D<T>& A,
01236                       ScalarField2D<T>& B )
01237 {
01238     Dot2D offset = computeRelativeDisplacement(A, B);
01239     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01240         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01241             PLB_ASSERT( A.get(iX,iY) >= T());
01242             B.get(iX+offset.x,iY+offset.y) = std::sqrt( A.get(iX,iY) );
01243         }
01244     }
01245 }
01246 
01247 template<typename T>
01248 ComputeScalarSqrtFunctional2D<T>* ComputeScalarSqrtFunctional2D<T>::clone() const
01249 {
01250     return new ComputeScalarSqrtFunctional2D<T>(*this);
01251 }
01252 
01253 template<typename T>
01254 void ComputeScalarSqrtFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01255     modified[0] = modif::nothing;
01256     modified[1] = modif::staticVariables;
01257 }
01258 
01259 template<typename T>
01260 BlockDomain::DomainT ComputeScalarSqrtFunctional2D<T>::appliesTo() const {
01261     return BlockDomain::bulkAndEnvelope;
01262 }
01263 
01264 /* ******** compute sqrt functional 2D ************************************* */
01265 
01266 template<typename T>
01267 void ComputeScalarLogFunctional2D<T>::process (
01268         Box2D domain, ScalarField2D<T>& A,
01269                       ScalarField2D<T>& B )
01270 {
01271     Dot2D offset = computeRelativeDisplacement(A, B);
01272     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01273         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01274             PLB_ASSERT( A.get(iX,iY) >= T());
01275             B.get(iX+offset.x,iY+offset.y) = std::log( A.get(iX,iY) );
01276         }
01277     }
01278 }
01279 
01280 template<typename T>
01281 ComputeScalarLogFunctional2D<T>* ComputeScalarLogFunctional2D<T>::clone() const
01282 {
01283     return new ComputeScalarLogFunctional2D<T>(*this);
01284 }
01285 
01286 template<typename T>
01287 void ComputeScalarLogFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01288     modified[0] = modif::nothing;
01289     modified[1] = modif::staticVariables;
01290 }
01291 
01292 template<typename T>
01293 BlockDomain::DomainT ComputeScalarLogFunctional2D<T>::appliesTo() const {
01294     return BlockDomain::bulkAndEnvelope;
01295 }
01296 
01297 /* ******** compute sqrt functional 2D ************************************* */
01298 
01299 template<typename T, int nDim>
01300 void ComputeTensorSqrtFunctional2D<T,nDim>::process (
01301         Box2D domain, TensorField2D<T,nDim>& A,
01302                       TensorField2D<T,nDim>& B )
01303 {
01304     Dot2D offset = computeRelativeDisplacement(A, B);
01305     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01306         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01307             for (plint iD = 0; iD < nDim; ++iD) {
01308                 PLB_ASSERT( A.get(iX,iY)[iD] >= T());
01309                 B.get(iX+offset.x,iY+offset.y)[iD] = std::sqrt( A.get(iX,iY)[iD] );
01310             }
01311         }
01312     }
01313 }
01314 
01315 template<typename T, int nDim>
01316 ComputeTensorSqrtFunctional2D<T,nDim>* ComputeTensorSqrtFunctional2D<T,nDim>::clone() const
01317 {
01318     return new ComputeTensorSqrtFunctional2D<T,nDim>(*this);
01319 }
01320 
01321 template<typename T, int nDim>
01322 void ComputeTensorSqrtFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01323     modified[0] = modif::nothing;
01324     modified[1] = modif::staticVariables;
01325 }
01326 
01327 template<typename T, int nDim>
01328 BlockDomain::DomainT ComputeTensorSqrtFunctional2D<T,nDim>::appliesTo() const {
01329     return BlockDomain::bulkAndEnvelope;
01330 }
01331 
01332 
01333 /* ******** A_lt_alpha_functional2D ************************************* */
01334 
01335 template<typename T>
01336 A_lt_alpha_functional2D<T>::A_lt_alpha_functional2D(T alpha_)
01337     : alpha(alpha_)
01338 { }
01339 
01340 template<typename T>
01341 void A_lt_alpha_functional2D<T>::process (
01342         Box2D domain, ScalarField2D<T>& A, ScalarField2D<int>& result )
01343 {
01344     Dot2D offset = computeRelativeDisplacement(A, result);
01345     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01346         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01347             result.get(iX+offset.x,iY+offset.y) =
01348                 A.get(iX,iY) < alpha ? 1:0;
01349         }
01350     }
01351 }
01352 
01353 template<typename T>
01354 A_lt_alpha_functional2D<T>* A_lt_alpha_functional2D<T>::clone() const {
01355     return new A_lt_alpha_functional2D<T>(*this);
01356 }
01357 
01358 template<typename T>
01359 void A_lt_alpha_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01360     modified[0] = modif::nothing;
01361     modified[1] = modif::staticVariables;
01362 }
01363 
01364 template<typename T>
01365 BlockDomain::DomainT A_lt_alpha_functional2D<T>::appliesTo() const {
01366     return BlockDomain::bulkAndEnvelope;
01367 }
01368 
01369 
01370 /* ******** A_gt_alpha_functional2D ************************************* */
01371 
01372 template<typename T>
01373 A_gt_alpha_functional2D<T>::A_gt_alpha_functional2D(T alpha_)
01374     : alpha(alpha_)
01375 { }
01376 
01377 template<typename T>
01378 void A_gt_alpha_functional2D<T>::process (
01379         Box2D domain, ScalarField2D<T>& A, ScalarField2D<int>& result )
01380 {
01381     Dot2D offset = computeRelativeDisplacement(A, result);
01382     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01383         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01384             result.get(iX+offset.x,iY+offset.y) =
01385                 A.get(iX,iY) > alpha ? 1:0;
01386         }
01387     }
01388 }
01389 
01390 template<typename T>
01391 A_gt_alpha_functional2D<T>* A_gt_alpha_functional2D<T>::clone() const {
01392     return new A_gt_alpha_functional2D<T>(*this);
01393 }
01394 
01395 template<typename T>
01396 void A_gt_alpha_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01397     modified[0] = modif::nothing;
01398     modified[1] = modif::staticVariables;
01399 }
01400 
01401 template<typename T>
01402 BlockDomain::DomainT A_gt_alpha_functional2D<T>::appliesTo() const {
01403     return BlockDomain::bulkAndEnvelope;
01404 }
01405 
01406 
01407 /* ******** A_plus_alpha_functional2D ************************************* */
01408 
01409 template<typename T>
01410 A_plus_alpha_functional2D<T>::A_plus_alpha_functional2D(T alpha_)
01411     : alpha(alpha_)
01412 { }
01413 
01414 template<typename T>
01415 void A_plus_alpha_functional2D<T>::process (
01416         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& result )
01417 {
01418     Dot2D offset = computeRelativeDisplacement(A, result);
01419     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01420         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01421             result.get(iX+offset.x,iY+offset.y) = A.get(iX,iY) + alpha;
01422         }
01423     }
01424 }
01425 
01426 template<typename T>
01427 A_plus_alpha_functional2D<T>* A_plus_alpha_functional2D<T>::clone() const {
01428     return new A_plus_alpha_functional2D<T>(*this);
01429 }
01430 
01431 template<typename T>
01432 void A_plus_alpha_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01433     modified[0] = modif::nothing;
01434     modified[1] = modif::staticVariables;
01435 }
01436 
01437 template<typename T>
01438 BlockDomain::DomainT A_plus_alpha_functional2D<T>::appliesTo() const {
01439     return BlockDomain::bulkAndEnvelope;
01440 }
01441 
01442 
01443 /* ******** A_minus_alpha_functional2D ************************************** */
01444 
01445 template<typename T>
01446 A_minus_alpha_functional2D<T>::A_minus_alpha_functional2D(T alpha_)
01447     : alpha(alpha_)
01448 { }
01449 
01450 template<typename T>
01451 void A_minus_alpha_functional2D<T>::process (
01452         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& result )
01453 {
01454     Dot2D offset = computeRelativeDisplacement(A, result);
01455     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01456         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01457             result.get(iX+offset.x,iY+offset.y) = A.get(iX,iY) - alpha;
01458         }
01459     }
01460 }
01461 
01462 template<typename T>
01463 A_minus_alpha_functional2D<T>* A_minus_alpha_functional2D<T>::clone() const {
01464     return new A_minus_alpha_functional2D<T>(*this);
01465 }
01466 
01467 template<typename T>
01468 void A_minus_alpha_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01469     modified[0] = modif::nothing;
01470     modified[1] = modif::staticVariables;
01471 }
01472 
01473 template<typename T>
01474 BlockDomain::DomainT A_minus_alpha_functional2D<T>::appliesTo() const {
01475     return BlockDomain::bulkAndEnvelope;
01476 }
01477 
01478 
01479 /* ******** Alpha_minus_A_functional2D ************************************* */
01480 
01481 template<typename T>
01482 Alpha_minus_A_functional2D<T>::Alpha_minus_A_functional2D(T alpha_)
01483     : alpha(alpha_)
01484 { }
01485 
01486 template<typename T>
01487 void Alpha_minus_A_functional2D<T>::process (
01488         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& result )
01489 {
01490     Dot2D offset = computeRelativeDisplacement(A, result);
01491     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01492         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01493             result.get(iX+offset.x,iY+offset.y) = alpha - A.get(iX,iY);
01494         }
01495     }
01496 }
01497 
01498 template<typename T>
01499 Alpha_minus_A_functional2D<T>* Alpha_minus_A_functional2D<T>::clone() const {
01500     return new Alpha_minus_A_functional2D<T>(*this);
01501 }
01502 
01503 template<typename T>
01504 void Alpha_minus_A_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01505     modified[0] = modif::nothing;
01506     modified[1] = modif::staticVariables;
01507 }
01508 
01509 template<typename T>
01510 BlockDomain::DomainT Alpha_minus_A_functional2D<T>::appliesTo() const {
01511     return BlockDomain::bulkAndEnvelope;
01512 }
01513 
01514 
01515 
01516 /* ******** A_times_alpha_functional2D ************************************* */
01517 
01518 template<typename T>
01519 A_times_alpha_functional2D<T>::A_times_alpha_functional2D(T alpha_)
01520     : alpha(alpha_)
01521 { }
01522 
01523 template<typename T>
01524 void A_times_alpha_functional2D<T>::process (
01525         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& result )
01526 {
01527     Dot2D offset = computeRelativeDisplacement(A, result);
01528     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01529         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01530             result.get(iX+offset.x,iY+offset.y) = A.get(iX,iY) * alpha;
01531         }
01532     }
01533 }
01534 
01535 template<typename T>
01536 A_times_alpha_functional2D<T>* A_times_alpha_functional2D<T>::clone() const {
01537     return new A_times_alpha_functional2D<T>(*this);
01538 }
01539 
01540 template<typename T>
01541 void A_times_alpha_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01542     modified[0] = modif::nothing;
01543     modified[1] = modif::staticVariables;
01544 }
01545 
01546 template<typename T>
01547 BlockDomain::DomainT A_times_alpha_functional2D<T>::appliesTo() const {
01548     return BlockDomain::bulkAndEnvelope;
01549 }
01550 
01551 /* ******** Tensor_A_times_alpha_functional2D ************************************* */
01552 
01553 template<typename T, int nDim>
01554 Tensor_A_times_alpha_functional2D<T,nDim>::Tensor_A_times_alpha_functional2D(T alpha_)
01555     : alpha(alpha_)
01556 { }
01557 
01558 template<typename T, int nDim>
01559 void Tensor_A_times_alpha_functional2D<T,nDim>::process (
01560     Box2D domain, TensorField2D<T,nDim>& A, TensorField2D<T,nDim>& result )
01561 {
01562     Dot2D offset = computeRelativeDisplacement(A, result);
01563     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01564         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01565             for (plint iD = 0; iD < nDim; ++iD) {
01566                 result.get(iX+offset.x,iY+offset.y)[iD] = A.get(iX,iY)[iD] * alpha;
01567             }
01568         }
01569     }
01570 }
01571 
01572 template<typename T, int nDim>
01573 Tensor_A_times_alpha_functional2D<T,nDim>* Tensor_A_times_alpha_functional2D<T,nDim>::clone() const {
01574     return new Tensor_A_times_alpha_functional2D<T,nDim>(*this);
01575 }
01576 
01577 template<typename T, int nDim>
01578 void Tensor_A_times_alpha_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01579     modified[0] = modif::nothing;
01580     modified[1] = modif::staticVariables;
01581 }
01582 
01583 template<typename T, int nDim>
01584 BlockDomain::DomainT Tensor_A_times_alpha_functional2D<T,nDim>::appliesTo() const {
01585     return BlockDomain::bulkAndEnvelope;
01586 }
01587 
01588 
01589 /* ******** A_dividedBy_alpha_functional2D ************************************* */
01590 
01591 template<typename T>
01592 A_dividedBy_alpha_functional2D<T>::A_dividedBy_alpha_functional2D(T alpha_)
01593     : alpha(alpha_)
01594 { }
01595 
01596 template<typename T>
01597 void A_dividedBy_alpha_functional2D<T>::process (
01598         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& result )
01599 {
01600     Dot2D offset = computeRelativeDisplacement(A, result);
01601     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01602         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01603             result.get(iX+offset.x,iY+offset.y) = A.get(iX,iY) / alpha;
01604         }
01605     }
01606 }
01607 
01608 template<typename T>
01609 A_dividedBy_alpha_functional2D<T>* A_dividedBy_alpha_functional2D<T>::clone() const {
01610     return new A_dividedBy_alpha_functional2D<T>(*this);
01611 }
01612 
01613 template<typename T>
01614 void A_dividedBy_alpha_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01615     modified[0] = modif::nothing;
01616     modified[1] = modif::staticVariables;
01617 }
01618 
01619 template<typename T>
01620 BlockDomain::DomainT A_dividedBy_alpha_functional2D<T>::appliesTo() const {
01621     return BlockDomain::bulkAndEnvelope;
01622 }
01623 
01624 
01625 /* ******** Alpha_dividedBy_A_functional2D ************************************* */
01626 
01627 template<typename T>
01628 Alpha_dividedBy_A_functional2D<T>::Alpha_dividedBy_A_functional2D(T alpha_)
01629     : alpha(alpha_)
01630 { }
01631 
01632 template<typename T>
01633 void Alpha_dividedBy_A_functional2D<T>::process (
01634         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& result )
01635 {
01636     Dot2D offset = computeRelativeDisplacement(A, result);
01637     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01638         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01639             result.get(iX+offset.x,iY+offset.y) = alpha / A.get(iX,iY);
01640         }
01641     }
01642 }
01643 
01644 template<typename T>
01645 Alpha_dividedBy_A_functional2D<T>* Alpha_dividedBy_A_functional2D<T>::clone() const {
01646     return new Alpha_dividedBy_A_functional2D<T>(*this);
01647 }
01648 
01649 template<typename T>
01650 void Alpha_dividedBy_A_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01651     modified[0] = modif::nothing;
01652     modified[1] = modif::staticVariables;
01653 }
01654 
01655 template<typename T>
01656 BlockDomain::DomainT Alpha_dividedBy_A_functional2D<T>::appliesTo() const {
01657     return BlockDomain::bulkAndEnvelope;
01658 }
01659 
01660 
01661 
01662 /* ******** A_plus_alpha_inplace_functional2D ************************************* */
01663 
01664 template<typename T>
01665 A_plus_alpha_inplace_functional2D<T>::A_plus_alpha_inplace_functional2D(T alpha_)
01666     : alpha(alpha_)
01667 { }
01668 
01669 template<typename T>
01670 void A_plus_alpha_inplace_functional2D<T>::process (
01671         Box2D domain, ScalarField2D<T>& A)
01672 {
01673     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01674         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01675             A.get(iX,iY) += alpha;
01676         }
01677     }
01678 }
01679 
01680 template<typename T>
01681 A_plus_alpha_inplace_functional2D<T>* A_plus_alpha_inplace_functional2D<T>::clone() const {
01682     return new A_plus_alpha_inplace_functional2D<T>(*this);
01683 }
01684 
01685 template<typename T>
01686 void A_plus_alpha_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01687     modified[0] = modif::staticVariables;
01688 }
01689 
01690 template<typename T>
01691 BlockDomain::DomainT A_plus_alpha_inplace_functional2D<T>::appliesTo() const {
01692     return BlockDomain::bulkAndEnvelope;
01693 }
01694 
01695 
01696 /* ******** A_minus_alpha_inplace_functional2D ************************************** */
01697 
01698 template<typename T>
01699 A_minus_alpha_inplace_functional2D<T>::A_minus_alpha_inplace_functional2D(T alpha_)
01700     : alpha(alpha_)
01701 { }
01702 
01703 template<typename T>
01704 void A_minus_alpha_inplace_functional2D<T>::process (
01705         Box2D domain, ScalarField2D<T>& A)
01706 {
01707     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01708         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01709             A.get(iX,iY) -= alpha;
01710         }
01711     }
01712 }
01713 
01714 template<typename T>
01715 A_minus_alpha_inplace_functional2D<T>* A_minus_alpha_inplace_functional2D<T>::clone() const {
01716     return new A_minus_alpha_inplace_functional2D<T>(*this);
01717 }
01718 
01719 template<typename T>
01720 void A_minus_alpha_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01721     modified[0] = modif::staticVariables;
01722 }
01723 
01724 template<typename T>
01725 BlockDomain::DomainT A_minus_alpha_inplace_functional2D<T>::appliesTo() const {
01726     return BlockDomain::bulkAndEnvelope;
01727 }
01728 
01729 
01730 /* ******** A_times_alpha_inplace_functional2D ************************************* */
01731 
01732 template<typename T>
01733 A_times_alpha_inplace_functional2D<T>::A_times_alpha_inplace_functional2D(T alpha_)
01734     : alpha(alpha_)
01735 { }
01736 
01737 template<typename T>
01738 void A_times_alpha_inplace_functional2D<T>::process (
01739         Box2D domain, ScalarField2D<T>& A )
01740 {
01741     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01742         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01743             A.get(iX,iY) *= alpha;
01744         }
01745     }
01746 }
01747 
01748 template<typename T>
01749 A_times_alpha_inplace_functional2D<T>* A_times_alpha_inplace_functional2D<T>::clone() const {
01750     return new A_times_alpha_inplace_functional2D<T>(*this);
01751 }
01752 
01753 template<typename T>
01754 void A_times_alpha_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01755     modified[0] = modif::staticVariables;
01756 }
01757 
01758 template<typename T>
01759 BlockDomain::DomainT A_times_alpha_inplace_functional2D<T>::appliesTo() const {
01760     return BlockDomain::bulkAndEnvelope;
01761 }
01762 
01763 
01764 /* ******** A_dividedBy_alpha_inplace_functional2D ************************************* */
01765 
01766 template<typename T>
01767 A_dividedBy_alpha_inplace_functional2D<T>::A_dividedBy_alpha_inplace_functional2D(T alpha_)
01768     : alpha(alpha_)
01769 { }
01770 
01771 template<typename T>
01772 void A_dividedBy_alpha_inplace_functional2D<T>::process (
01773         Box2D domain, ScalarField2D<T>& A )
01774 {
01775     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01776         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01777             A.get(iX,iY) /= alpha;
01778         }
01779     }
01780 }
01781 
01782 template<typename T>
01783 A_dividedBy_alpha_inplace_functional2D<T>* A_dividedBy_alpha_inplace_functional2D<T>::clone() const {
01784     return new A_dividedBy_alpha_inplace_functional2D<T>(*this);
01785 }
01786 
01787 template<typename T>
01788 void A_dividedBy_alpha_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01789     modified[0] = modif::staticVariables;
01790 }
01791 
01792 template<typename T>
01793 BlockDomain::DomainT A_dividedBy_alpha_inplace_functional2D<T>::appliesTo() const {
01794     return BlockDomain::bulkAndEnvelope;
01795 }
01796 
01797 
01798 /* ******** A_lt_B_functional2D ****************************************** */
01799 
01800 template<typename T>
01801 void A_lt_B_functional2D<T>::processGenericBlocks (
01802         Box2D domain, std::vector<AtomicBlock2D*> fields )
01803 {
01804     PLB_PRECONDITION( fields.size()==3 );
01805     ScalarField2D<T>& A = *dynamic_cast<ScalarField2D<T>*>(fields[0]);
01806     ScalarField2D<T>& B = *dynamic_cast<ScalarField2D<T>*>(fields[1]);
01807     ScalarField2D<int>& result = *dynamic_cast<ScalarField2D<int>*>(fields[2]);
01808     Dot2D offsetB      = computeRelativeDisplacement(A,B);
01809     Dot2D offsetResult = computeRelativeDisplacement(A,result);
01810     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01811         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01812             result.get(iX+offsetResult.x,iY+offsetResult.y)
01813                 = A.get(iX,iY) < B.get(iX+offsetB.x,iY+offsetB.y) ? 1:0;
01814         }
01815     }
01816 }
01817 
01818 template<typename T>
01819 A_lt_B_functional2D<T>* A_lt_B_functional2D<T>::clone() const {
01820     return new A_lt_B_functional2D<T>(*this);
01821 }
01822 
01823 template<typename T>
01824 void A_lt_B_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01825     modified[0] = modif::nothing;
01826     modified[1] = modif::nothing;
01827     modified[2] = modif::staticVariables;
01828 }
01829 
01830 template<typename T>
01831 BlockDomain::DomainT A_lt_B_functional2D<T>::appliesTo() const {
01832     return BlockDomain::bulkAndEnvelope;
01833 }
01834 
01835 
01836 /* ******** A_gt_B_functional2D ****************************************** */
01837 
01838 template<typename T>
01839 void A_gt_B_functional2D<T>::processGenericBlocks (
01840         Box2D domain, std::vector<AtomicBlock2D*> fields )
01841 {
01842     PLB_PRECONDITION( fields.size()==3 );
01843     ScalarField2D<T>& A = *dynamic_cast<ScalarField2D<T>*>(fields[0]);
01844     ScalarField2D<T>& B = *dynamic_cast<ScalarField2D<T>*>(fields[1]);
01845     ScalarField2D<int>& result = *dynamic_cast<ScalarField2D<int>*>(fields[2]);
01846     Dot2D offsetB      = computeRelativeDisplacement(A,B);
01847     Dot2D offsetResult = computeRelativeDisplacement(A,result);
01848     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01849         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01850             result.get(iX+offsetResult.x,iY+offsetResult.y)
01851                 = A.get(iX,iY) > B.get(iX+offsetB.x,iY+offsetB.y) ? 1:0;
01852         }
01853     }
01854 }
01855 
01856 template<typename T>
01857 A_gt_B_functional2D<T>* A_gt_B_functional2D<T>::clone() const {
01858     return new A_gt_B_functional2D<T>(*this);
01859 }
01860 
01861 template<typename T>
01862 void A_gt_B_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01863     modified[0] = modif::nothing;
01864     modified[1] = modif::nothing;
01865     modified[2] = modif::staticVariables;
01866 }
01867 
01868 template<typename T>
01869 BlockDomain::DomainT A_gt_B_functional2D<T>::appliesTo() const {
01870     return BlockDomain::bulkAndEnvelope;
01871 }
01872 
01873 
01874 /* ******** A_plus_B_functional2D ****************************************** */
01875 
01876 template<typename T>
01877 void A_plus_B_functional2D<T>::process (
01878         Box2D domain, std::vector<ScalarField2D<T>*> fields )
01879 {
01880     PLB_PRECONDITION( fields.size()==3 );
01881     ScalarField2D<T>& A = *fields[0];
01882     ScalarField2D<T>& B = *fields[1];
01883     ScalarField2D<T>& result = *fields[2];
01884     Dot2D offsetB      = computeRelativeDisplacement(A,B);
01885     Dot2D offsetResult = computeRelativeDisplacement(A,result);
01886     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01887         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01888             result.get(iX+offsetResult.x,iY+offsetResult.y)
01889                 = A.get(iX,iY) + B.get(iX+offsetB.x,iY+offsetB.y);
01890         }
01891     }
01892 }
01893 
01894 template<typename T>
01895 A_plus_B_functional2D<T>* A_plus_B_functional2D<T>::clone() const {
01896     return new A_plus_B_functional2D<T>(*this);
01897 }
01898 
01899 template<typename T>
01900 void A_plus_B_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01901     modified[0] = modif::nothing;
01902     modified[1] = modif::nothing;
01903     modified[2] = modif::staticVariables;
01904 }
01905 
01906 template<typename T>
01907 BlockDomain::DomainT A_plus_B_functional2D<T>::appliesTo() const {
01908     return BlockDomain::bulkAndEnvelope;
01909 }
01910 
01911 
01912 /* ******** A_minus_B_functional2D ****************************************** */
01913 
01914 template<typename T>
01915 void A_minus_B_functional2D<T>::process (
01916         Box2D domain, std::vector<ScalarField2D<T>*> fields )
01917 {
01918     PLB_PRECONDITION( fields.size()==3 );
01919     ScalarField2D<T>& A = *fields[0];
01920     ScalarField2D<T>& B = *fields[1];
01921     ScalarField2D<T>& result = *fields[2];
01922     Dot2D offsetB      = computeRelativeDisplacement(A,B);
01923     Dot2D offsetResult = computeRelativeDisplacement(A,result);
01924     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01925         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01926             result.get(iX+offsetResult.x,iY+offsetResult.y)
01927                 = A.get(iX,iY) - B.get(iX+offsetB.x,iY+offsetB.y);
01928         }
01929     }
01930 }
01931 
01932 template<typename T>
01933 A_minus_B_functional2D<T>* A_minus_B_functional2D<T>::clone() const {
01934     return new A_minus_B_functional2D<T>(*this);
01935 }
01936 
01937 template<typename T>
01938 void A_minus_B_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01939     modified[0] = modif::nothing;
01940     modified[1] = modif::nothing;
01941     modified[2] = modif::staticVariables;
01942 }
01943 
01944 template<typename T>
01945 BlockDomain::DomainT A_minus_B_functional2D<T>::appliesTo() const {
01946     return BlockDomain::bulkAndEnvelope;
01947 }
01948 
01949 
01950 /* ******** A_times_B_functional2D ****************************************** */
01951 
01952 template<typename T>
01953 void A_times_B_functional2D<T>::process (
01954         Box2D domain, std::vector<ScalarField2D<T>*> fields )
01955 {
01956     PLB_PRECONDITION( fields.size()==3 );
01957     ScalarField2D<T>& A = *fields[0];
01958     ScalarField2D<T>& B = *fields[1];
01959     ScalarField2D<T>& result = *fields[2];
01960     Dot2D offsetB      = computeRelativeDisplacement(A,B);
01961     Dot2D offsetResult = computeRelativeDisplacement(A,result);
01962     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
01963         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
01964             result.get(iX+offsetResult.x,iY+offsetResult.y)
01965                 = A.get(iX,iY) * B.get(iX+offsetB.x,iY+offsetB.y);
01966         }
01967     }
01968 }
01969 
01970 template<typename T>
01971 A_times_B_functional2D<T>* A_times_B_functional2D<T>::clone() const {
01972     return new A_times_B_functional2D<T>(*this);
01973 }
01974 
01975 template<typename T>
01976 void A_times_B_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
01977     modified[0] = modif::nothing;
01978     modified[1] = modif::nothing;
01979     modified[2] = modif::staticVariables;
01980 }
01981 
01982 template<typename T>
01983 BlockDomain::DomainT A_times_B_functional2D<T>::appliesTo() const {
01984     return BlockDomain::bulkAndEnvelope;
01985 }
01986 
01987 
01988 /* ******** A_dividedBy_B_functional2D ****************************************** */
01989 
01990 template<typename T>
01991 void A_dividedBy_B_functional2D<T>::process (
01992         Box2D domain, std::vector<ScalarField2D<T>*> fields )
01993 {
01994     PLB_PRECONDITION( fields.size()==3 );
01995     ScalarField2D<T>& A = *fields[0];
01996     ScalarField2D<T>& B = *fields[1];
01997     ScalarField2D<T>& result = *fields[2];
01998     Dot2D offsetB      = computeRelativeDisplacement(A,B);
01999     Dot2D offsetResult = computeRelativeDisplacement(A,result);
02000     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02001         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02002             result.get(iX+offsetResult.x,iY+offsetResult.y)
02003                 = A.get(iX,iY) / B.get(iX+offsetB.x,iY+offsetB.y);
02004         }
02005     }
02006 }
02007 
02008 template<typename T>
02009 A_dividedBy_B_functional2D<T>* A_dividedBy_B_functional2D<T>::clone() const {
02010     return new A_dividedBy_B_functional2D<T>(*this);
02011 }
02012 
02013 template<typename T>
02014 void A_dividedBy_B_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02015     modified[0] = modif::nothing;
02016     modified[1] = modif::nothing;
02017     modified[2] = modif::staticVariables;
02018 }
02019 
02020 template<typename T>
02021 BlockDomain::DomainT A_dividedBy_B_functional2D<T>::appliesTo() const {
02022     return BlockDomain::bulkAndEnvelope;
02023 }
02024 
02025 
02026 /* ******** A_plus_B_inplace_functional2D ****************************************** */
02027 
02028 template<typename T>
02029 void A_plus_B_inplace_functional2D<T>::process (
02030         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& B)
02031 {
02032     Dot2D offset = computeRelativeDisplacement(A,B);
02033     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02034         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02035             A.get(iX,iY) += B.get(iX+offset.x,iY+offset.y);
02036         }
02037     }
02038 }
02039 
02040 template<typename T>
02041 A_plus_B_inplace_functional2D<T>* A_plus_B_inplace_functional2D<T>::clone() const {
02042     return new A_plus_B_inplace_functional2D<T>(*this);
02043 }
02044 
02045 template<typename T>
02046 void A_plus_B_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02047     modified[0] = modif::staticVariables;
02048     modified[1] = modif::nothing;
02049 }
02050 
02051 template<typename T>
02052 BlockDomain::DomainT A_plus_B_inplace_functional2D<T>::appliesTo() const {
02053     return BlockDomain::bulkAndEnvelope;
02054 }
02055 
02056 
02057 /* ******** A_minus_B_inplace_functional2D ****************************************** */
02058 
02059 template<typename T>
02060 void A_minus_B_inplace_functional2D<T>::process (
02061         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& B)
02062 {
02063     Dot2D offset = computeRelativeDisplacement(A,B);
02064     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02065         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02066             A.get(iX,iY) -= B.get(iX+offset.x,iY+offset.y);
02067         }
02068     }
02069 }
02070 
02071 template<typename T>
02072 A_minus_B_inplace_functional2D<T>* A_minus_B_inplace_functional2D<T>::clone() const {
02073     return new A_minus_B_inplace_functional2D<T>(*this);
02074 }
02075 
02076 template<typename T>
02077 void A_minus_B_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02078     modified[0] = modif::staticVariables;
02079     modified[1] = modif::nothing;
02080 }
02081 
02082 template<typename T>
02083 BlockDomain::DomainT A_minus_B_inplace_functional2D<T>::appliesTo() const {
02084     return BlockDomain::bulkAndEnvelope;
02085 }
02086 
02087 
02088 /* ******** A_times_B_inplace_functional2D ****************************************** */
02089 
02090 template<typename T>
02091 void A_times_B_inplace_functional2D<T>::process (
02092         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& B)
02093 {
02094     Dot2D offset = computeRelativeDisplacement(A,B);
02095     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02096         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02097             A.get(iX,iY) *= B.get(iX+offset.x,iY+offset.y);
02098         }
02099     }
02100 }
02101 
02102 template<typename T>
02103 A_times_B_inplace_functional2D<T>* A_times_B_inplace_functional2D<T>::clone() const {
02104     return new A_times_B_inplace_functional2D<T>(*this);
02105 }
02106 
02107 template<typename T>
02108 void A_times_B_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02109     modified[0] = modif::staticVariables;
02110     modified[1] = modif::nothing;
02111 }
02112 
02113 template<typename T>
02114 BlockDomain::DomainT A_times_B_inplace_functional2D<T>::appliesTo() const {
02115     return BlockDomain::bulkAndEnvelope;
02116 }
02117 
02118 
02119 /* ******** A_dividedBy_B_inplace_functional2D ****************************************** */
02120 
02121 template<typename T>
02122 void A_dividedBy_B_inplace_functional2D<T>::process (
02123         Box2D domain, ScalarField2D<T>& A, ScalarField2D<T>& B)
02124 {
02125     Dot2D offset = computeRelativeDisplacement(A,B);
02126     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02127         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02128             A.get(iX,iY) -= B.get(iX+offset.x,iY+offset.y);
02129         }
02130     }
02131 }
02132 
02133 template<typename T>
02134 A_dividedBy_B_inplace_functional2D<T>* A_dividedBy_B_inplace_functional2D<T>::clone() const {
02135     return new A_dividedBy_B_inplace_functional2D<T>(*this);
02136 }
02137 
02138 template<typename T>
02139 void A_dividedBy_B_inplace_functional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02140     modified[0] = modif::staticVariables;
02141     modified[1] = modif::nothing;
02142 }
02143 
02144 template<typename T>
02145 BlockDomain::DomainT A_dividedBy_B_inplace_functional2D<T>::appliesTo() const {
02146     return BlockDomain::bulkAndEnvelope;
02147 }
02148 
02149 
02150 
02151 /* *************** PART III ****************************************** */
02152 /* *************** Analysis of the tensor-field ********************** */
02153 /* ******************************************************************* */
02154 
02156 namespace fdDataField {
02157 
02158 template<typename T, int nDim>
02159 inline T bulkXderiv (
02160         TensorField2D<T,nDim> const& velocity, plint iX, plint iY, int iD )
02161 {
02162     T dxu = fd::ctl_diff( velocity.get(iX+1,iY)[iD],
02163                           velocity.get(iX-1,iY)[iD] );
02164     return dxu;
02165 }
02166 
02167 template<typename T, int nDim>
02168 inline T bulkYderiv (
02169         TensorField2D<T,nDim> const& velocity, plint iX, plint iY, int iD )
02170 {
02171     T dyu = fd::ctl_diff( velocity.get(iX,iY+1)[iD],
02172                           velocity.get(iX,iY-1)[iD] );
02173     return dyu;
02174 }
02175 
02176 template<typename T, int nDim>
02177 inline T edgeXderiv (
02178         TensorField2D<T,nDim> const& velocity, int direction, int orientation,
02179         plint iX, plint iY, int iD )
02180 {
02181     if (direction==0) {
02182         return -orientation *
02183             fd::o1_fwd_diff( velocity.get(iX              ,iY)[iD],
02184                              velocity.get(iX-1*orientation,iY)[iD] );
02185     }
02186     else {
02187         return bulkXderiv(velocity, iX,iY, iD);
02188     }
02189 }
02190 
02191 template<typename T, int nDim>
02192 inline T edgeYderiv (
02193         TensorField2D<T,nDim> const& velocity, int direction, int orientation,
02194         plint iX, plint iY, int iD )
02195 {
02196     if (direction==1) {
02197         return -orientation *
02198             fd::o1_fwd_diff( velocity.get(iX,iY              )[iD],
02199                               velocity.get(iX,iY-1*orientation)[iD] );
02200     }
02201     else {
02202         return bulkYderiv(velocity, iX,iY, iD);
02203     }
02204 }
02205 
02206 template<typename T, int nDim>
02207 inline T cornerXderiv (
02208         TensorField2D<T,nDim> const& velocity,
02209         int normalX, int normalY,
02210         plint iX, plint iY, int iD )
02211 {
02212     int orientation = normalX;
02213     return -orientation *
02214         fd::o1_fwd_diff( velocity.get(iX              ,iY)[iD],
02215                          velocity.get(iX-1*orientation,iY)[iD] );
02216 }
02217 
02218 template<typename T, int nDim>
02219 inline T cornerYderiv (
02220         TensorField2D<T,nDim> const& velocity,
02221         int normalX, int normalY,
02222         plint iX, plint iY, int iD )
02223 {
02224     int orientation = normalY;
02225     return -orientation *
02226         fd::o1_fwd_diff( velocity.get(iX,iY              )[iD],
02227                          velocity.get(iX,iY-1*orientation)[iD] );
02228 }
02229 
02230 template<typename T, int nDim>
02231 inline T bulkVorticity(TensorField2D<T,nDim> const& velocity, plint iX, plint iY)
02232 {
02233     T dxuy = bulkXderiv(velocity, iX,iY, 1);
02234     T dyux = bulkYderiv(velocity, iX,iY, 0);
02235     return dxuy - dyux;
02236 }
02237 
02238 template<typename T, int nDim>
02239 inline T edgeVorticity( TensorField2D<T,nDim> const& velocity, int direction, int orientation,
02240                         plint iX, plint iY )
02241 {
02242     T dxuy = edgeXderiv(velocity, direction, orientation, iX,iY, 1);
02243     T dyux = edgeYderiv(velocity, direction, orientation, iX,iY, 0);
02244     return dxuy - dyux;
02245 }
02246 
02247 template<typename T, int nDim>
02248 inline T cornerVorticity( TensorField2D<T,nDim> const& velocity, int normalX, int normalY,
02249                           plint iX, plint iY )
02250 {
02251     T dxuy = cornerXderiv(velocity, normalX, normalY, iX,iY, 1);
02252     T dyux = cornerYderiv(velocity, normalX, normalY, iX,iY, 0);
02253     return dxuy - dyux;
02254 }
02255 
02256 }  // fdDataField
02257 
02258 
02259 template<typename T1, typename T2, int nDim>
02260 void CopyConvertTensorFunctional2D<T1,T2,nDim>::process (
02261         Box2D domain, TensorField2D<T1,nDim>& field1,
02262                       TensorField2D<T2,nDim>& field2 )
02263 {
02264     Dot2D offset = computeRelativeDisplacement(field1, field2);
02265 
02266     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02267         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02268             for (int iDim=0; iDim<nDim; ++iDim) {
02269                 field2.get(iX+offset.x,iY+offset.y)[iDim] =
02270                     (T2) field1.get(iX,iY)[iDim];
02271             }
02272         }
02273     }
02274 }
02275 
02276 template<typename T1, typename T2, int nDim>
02277 CopyConvertTensorFunctional2D<T1,T2,nDim>* CopyConvertTensorFunctional2D<T1,T2,nDim>::clone() const
02278 {
02279     return new CopyConvertTensorFunctional2D<T1,T2,nDim>(*this);
02280 }
02281 
02282 template<typename T1, typename T2, int nDim>
02283 void CopyConvertTensorFunctional2D<T1,T2,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02284     modified[0] = modif::nothing;
02285     modified[1] = modif::staticVariables;
02286 }
02287 
02288 template<typename T1, typename T2, int nDim>
02289 BlockDomain::DomainT CopyConvertTensorFunctional2D<T1,T2,nDim>::appliesTo() const {
02290     return BlockDomain::bulk;
02291 }
02292 
02293 
02294 template<typename T, int nDim>
02295 void ExtractTensorSubDomainFunctional2D<T,nDim>::process (
02296         Box2D domain, TensorField2D<T,nDim>& field1,
02297                       TensorField2D<T,nDim>& field2 )
02298 {
02299     Dot2D offset = computeRelativeDisplacement(field1, field2);
02300     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02301         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02302             for (int iDim=0; iDim<nDim; ++iDim) {
02303                 field2.get(iX+offset.x,iY+offset.y)[iDim] = field1.get(iX,iY)[iDim];
02304             }
02305         }
02306     }
02307 }
02308 
02309 template<typename T, int nDim>
02310 ExtractTensorSubDomainFunctional2D<T,nDim>* ExtractTensorSubDomainFunctional2D<T,nDim>::clone() const
02311 {
02312     return new ExtractTensorSubDomainFunctional2D<T,nDim>(*this);
02313 }
02314 
02315 template<typename T, int nDim>
02316 void ExtractTensorSubDomainFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02317     modified[0] = modif::nothing;
02318     modified[1] = modif::staticVariables;
02319 }
02320 
02321 template<typename T, int nDim>
02322 BlockDomain::DomainT ExtractTensorSubDomainFunctional2D<T,nDim>::appliesTo() const {
02323     return BlockDomain::bulkAndEnvelope;
02324 }
02325 
02326 
02327 template<typename T, int nDim>
02328 ExtractTensorComponentFunctional2D<T,nDim>::ExtractTensorComponentFunctional2D(int iComponent_)
02329     : iComponent(iComponent_)
02330 { }
02331 
02332 template<typename T, int nDim>
02333 void ExtractTensorComponentFunctional2D<T,nDim>::process (
02334         Box2D domain, ScalarField2D<T>& scalarField,
02335                       TensorField2D<T,nDim>& tensorField )
02336 {
02337     Dot2D offset = computeRelativeDisplacement(scalarField, tensorField);
02338     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02339         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02340             scalarField.get(iX,iY) = tensorField.get(iX+offset.x,iY+offset.y)[iComponent];
02341         }
02342     }
02343 }
02344 
02345 template<typename T, int nDim>
02346 ExtractTensorComponentFunctional2D<T,nDim>* ExtractTensorComponentFunctional2D<T,nDim>::clone() const
02347 {
02348     return new ExtractTensorComponentFunctional2D<T,nDim>(*this);
02349 }
02350 
02351 template<typename T, int nDim>
02352 void ExtractTensorComponentFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02353     modified[0] = modif::staticVariables;
02354     modified[1] = modif::nothing;
02355 }
02356 
02357 template<typename T, int nDim>
02358 BlockDomain::DomainT ExtractTensorComponentFunctional2D<T,nDim>::appliesTo() const {
02359     return BlockDomain::bulkAndEnvelope;
02360 }
02361 
02362 
02363 template<typename T, int nDim>
02364 void ComputeNormFunctional2D<T,nDim>::process (
02365         Box2D domain, ScalarField2D<T>& scalarField,
02366                       TensorField2D<T,nDim>& tensorField )
02367 {
02368     Dot2D offset = computeRelativeDisplacement(scalarField, tensorField);
02369     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02370         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02371             scalarField.get(iX,iY) = std::sqrt( VectorTemplateImpl<T,nDim>::normSqr (
02372                                                     tensorField.get(iX+offset.x,iY+offset.y) ) );
02373         }
02374     }
02375 }
02376 
02377 template<typename T, int nDim>
02378 ComputeNormFunctional2D<T,nDim>* ComputeNormFunctional2D<T,nDim>::clone() const
02379 {
02380     return new ComputeNormFunctional2D<T,nDim>(*this);
02381 }
02382 
02383 template<typename T, int nDim>
02384 void ComputeNormFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02385     modified[0] = modif::staticVariables;
02386     modified[1] = modif::nothing;
02387 }
02388 
02389 template<typename T, int nDim>
02390 BlockDomain::DomainT ComputeNormFunctional2D<T,nDim>::appliesTo() const {
02391     return BlockDomain::bulkAndEnvelope;
02392 }
02393 
02394 
02395 template<typename T, int nDim>
02396 void ComputeNormSqrFunctional2D<T,nDim>::process (
02397         Box2D domain, ScalarField2D<T>& scalarField,
02398                       TensorField2D<T,nDim>& tensorField )
02399 {
02400     Dot2D offset = computeRelativeDisplacement(scalarField, tensorField);
02401     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02402         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02403             T normSqr = T();
02404             for (plint iD = 0; iD < nDim; ++iD) {
02405                 normSqr += tensorField.get(iX+offset.x,iY+offset.y)[iD]
02406                                 *tensorField.get(iX+offset.x,iY+offset.y)[iD];
02407             }
02408             scalarField.get(iX,iY) = normSqr;
02409         }
02410     }
02411 }
02412 
02413 template<typename T, int nDim>
02414 ComputeNormSqrFunctional2D<T,nDim>* ComputeNormSqrFunctional2D<T,nDim>::clone() const
02415 {
02416     return new ComputeNormSqrFunctional2D<T,nDim>(*this);
02417 }
02418 
02419 template<typename T, int nDim>
02420 void ComputeNormSqrFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02421     modified[0] = modif::staticVariables;
02422     modified[1] = modif::nothing;
02423 }
02424 
02425 template<typename T, int nDim>
02426 BlockDomain::DomainT ComputeNormSqrFunctional2D<T,nDim>::appliesTo() const {
02427     return BlockDomain::bulkAndEnvelope;
02428 }
02429 
02430 
02431 template<typename T>
02432 void ComputeSymmetricTensorNormFunctional2D<T>::process (
02433         Box2D domain, ScalarField2D<T>& scalarField,
02434                       TensorField2D<T,3>& tensorField )
02435 {
02436     typedef SymmetricTensorImpl<T,2> tensor;
02437     Dot2D offset = computeRelativeDisplacement(scalarField, tensorField);
02438     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02439         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02440                 Array<T,3>& el = tensorField.get(iX+offset.x,iY+offset.y);
02441                 scalarField.get(iX,iY) = std::sqrt ( 
02442                         // Count diagonal components once ...
02443                                 util::sqr(el[tensor::xx]) + util::sqr(el[tensor::yy]) +
02444                         // .. and off-diagonal component twice, due to symmetry.
02445                         (T)2 * util::sqr(el[tensor::xy]) );
02446         }
02447     }
02448 }
02449 
02450 template<typename T>
02451 ComputeSymmetricTensorNormFunctional2D<T>* ComputeSymmetricTensorNormFunctional2D<T>::clone() const
02452 {
02453     return new ComputeSymmetricTensorNormFunctional2D<T>(*this);
02454 }
02455 
02456 template<typename T>
02457 void ComputeSymmetricTensorNormFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02458     modified[0] = modif::staticVariables;
02459     modified[1] = modif::nothing;
02460 }
02461 
02462 template<typename T>
02463 BlockDomain::DomainT ComputeSymmetricTensorNormFunctional2D<T>::appliesTo() const {
02464     return BlockDomain::bulkAndEnvelope;
02465 }
02466 
02467 
02468 template<typename T>
02469 void ComputeSymmetricTensorNormSqrFunctional2D<T>::process (
02470         Box2D domain, ScalarField2D<T>& scalarField,
02471                       TensorField2D<T,3>& tensorField )
02472 {
02473     typedef SymmetricTensorImpl<T,2> tensor;
02474     Dot2D offset = computeRelativeDisplacement(scalarField, tensorField);
02475     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02476         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02477             Array<T,3>& el = tensorField.get(iX+offset.x,iY+offset.y);
02478             scalarField.get(iX,iY) = 
02479                     // Count diagonal components once ...
02480                             util::sqr(el[tensor::xx]) + util::sqr(el[tensor::yy]) +
02481                     // .. and off-diagonal components twice, due to symmetry.
02482                     (T)2 * util::sqr(el[tensor::xy]);
02483         }
02484     }
02485 }
02486 
02487 template<typename T>
02488 ComputeSymmetricTensorNormSqrFunctional2D<T>* ComputeSymmetricTensorNormSqrFunctional2D<T>::clone() const
02489 {
02490     return new ComputeSymmetricTensorNormSqrFunctional2D<T>(*this);
02491 }
02492 
02493 template<typename T>
02494 void ComputeSymmetricTensorNormSqrFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02495     modified[0] = modif::staticVariables;
02496     modified[1] = modif::nothing;
02497 }
02498 
02499 template<typename T>
02500 BlockDomain::DomainT ComputeSymmetricTensorNormSqrFunctional2D<T>::appliesTo() const {
02501     return BlockDomain::bulkAndEnvelope;
02502 }
02503 
02504 template<typename T>
02505 void ComputeSymmetricTensorTraceFunctional2D<T>::process (
02506         Box2D domain, ScalarField2D<T>& scalarField,
02507                       TensorField2D<T,3>& tensorField )
02508 {
02509     typedef SymmetricTensorImpl<T,2> tensor;
02510     Dot2D offset = computeRelativeDisplacement(scalarField, tensorField);
02511     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02512         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02513             Array<T,3>& el = tensorField.get(iX+offset.x,iY+offset.y);
02514             scalarField.get(iX,iY) = el[tensor::xx] + el[tensor::yy];
02515         }
02516     }
02517 }
02518 
02519 template<typename T>
02520 ComputeSymmetricTensorTraceFunctional2D<T>* ComputeSymmetricTensorTraceFunctional2D<T>::clone() const
02521 {
02522     return new ComputeSymmetricTensorTraceFunctional2D<T>(*this);
02523 }
02524 
02525 template<typename T>
02526 void ComputeSymmetricTensorTraceFunctional2D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02527     modified[0] = modif::staticVariables;
02528     modified[1] = modif::nothing;
02529 }
02530 
02531 template<typename T>
02532 BlockDomain::DomainT ComputeSymmetricTensorTraceFunctional2D<T>::appliesTo() const {
02533     return BlockDomain::bulkAndEnvelope;
02534 }
02535 
02536 
02537 template<typename T, int nDim>
02538 void BoxBulkVorticityFunctional2D<T,nDim>::process (
02539         Box2D domain, ScalarField2D<T>& vorticity,
02540                       TensorField2D<T,nDim>& velocity )
02541 {
02542     Dot2D offset = computeRelativeDisplacement(vorticity, velocity);
02543     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02544         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02545             plint iX2 = iX+offset.x;
02546             plint iY2 = iY+offset.y;
02547             vorticity.get(iX,iY) =
02548                 fdDataField::bulkVorticity(velocity, iX2,iY2);
02549         }
02550     }
02551 }
02552 
02553 template<typename T, int nDim>
02554 BoxBulkVorticityFunctional2D<T,nDim>* BoxBulkVorticityFunctional2D<T,nDim>::clone() const
02555 {
02556     return new BoxBulkVorticityFunctional2D<T,nDim>(*this);
02557 }
02558 
02559 template<typename T, int nDim>
02560 void BoxBulkVorticityFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02561     modified[0] = modif::staticVariables;
02562     modified[1] = modif::nothing;
02563 }
02564 
02565 template<typename T, int nDim>
02566 BlockDomain::DomainT BoxBulkVorticityFunctional2D<T,nDim>::appliesTo() const {
02567     return BlockDomain::bulkAndEnvelope;
02568 }
02569 
02570 
02571 
02572 template<typename T, int nDim>
02573 void BoxVorticityFunctional2D<T,nDim>::processBulk (
02574         Box2D domain, ScalarField2D<T>& vorticity,
02575                       TensorField2D<T,nDim>& velocity )
02576 {
02577     Dot2D offset = computeRelativeDisplacement(vorticity, velocity);
02578     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02579         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02580             plint iX2 = iX+offset.x;
02581             plint iY2 = iY+offset.y;
02582             vorticity.get(iX,iY) =
02583                 fdDataField::bulkVorticity(velocity, iX2,iY2);
02584         }
02585     }
02586 }
02587 
02588 template<typename T, int nDim>
02589 void BoxVorticityFunctional2D<T,nDim>::processEdge (
02590         int direction, int orientation, Box2D domain,
02591         ScalarField2D<T>& vorticity, TensorField2D<T,nDim>& velocity )
02592 {
02593     Dot2D offset = computeRelativeDisplacement(vorticity, velocity);
02594     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02595         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02596             plint iX2 = iX+offset.x;
02597             plint iY2 = iY+offset.y;
02598             vorticity.get(iX,iY) =
02599                 fdDataField::edgeVorticity(velocity,direction,orientation, iX2,iY2);
02600         }
02601     }
02602 }
02603 
02604 template<typename T, int nDim>
02605 void BoxVorticityFunctional2D<T,nDim>::processCorner (
02606         int normalX, int normalY,  Box2D domain,
02607         ScalarField2D<T>& vorticity, TensorField2D<T,nDim>& velocity )
02608 {
02609     Dot2D offset = computeRelativeDisplacement(vorticity, velocity);
02610     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02611         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02612             plint iX2 = iX+offset.x;
02613             plint iY2 = iY+offset.y;
02614             vorticity.get(iX,iY) =
02615                 fdDataField::cornerVorticity(velocity,normalX,normalY, iX2,iY2);
02616         }
02617     }
02618 }
02619 
02620 template<typename T, int nDim>
02621 BoxVorticityFunctional2D<T,nDim>* BoxVorticityFunctional2D<T,nDim>::clone() const
02622 {
02623     return new BoxVorticityFunctional2D<T,nDim>(*this);
02624 }
02625 
02626 template<typename T, int nDim>
02627 void BoxVorticityFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02628     modified[0] = modif::staticVariables;
02629     modified[1] = modif::nothing;
02630 }
02631 
02632 
02633 template<typename T, int nDim>
02634 BlockDomain::DomainT BoxVorticityFunctional2D<T,nDim>::appliesTo() const {
02635     // Don't apply to envelope, because nearest neighbors need to be accessed.
02636     return BlockDomain::bulk;
02637 }
02638 
02639 
02640 template<typename T, int nDim>
02641 void BoxBulkStrainRateFunctional2D<T,nDim>::process (
02642         Box2D domain, TensorField2D<T,nDim>& velocity,
02643                       TensorField2D<T,SymmetricTensorImpl<T,nDim>::n>& S )
02644 {
02645     typedef SymmetricTensorImpl<T,nDim> tensor;
02646     Dot2D offset = computeRelativeDisplacement(velocity, S);
02647     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02648         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02649             plint iX2 = iX+offset.x;
02650             plint iY2 = iY+offset.y;
02651             Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2);
02652             el[tensor::xx] = fdDataField::bulkXderiv(velocity, iX, iY, 0);
02653             el[tensor::yy] = fdDataField::bulkYderiv(velocity, iX, iY, 1);
02654             el[tensor::xy] = ( fdDataField::bulkXderiv(velocity, iX, iY, 1) +
02655                                fdDataField::bulkYderiv(velocity, iX, iY, 0) ) / (T)2;
02656         }
02657     }
02658 }
02659 
02660 template<typename T, int nDim>
02661 BoxBulkStrainRateFunctional2D<T,nDim>* BoxBulkStrainRateFunctional2D<T,nDim>::clone() const
02662 {
02663     return new BoxBulkStrainRateFunctional2D<T,nDim>(*this);
02664 }
02665 
02666 template<typename T, int nDim>
02667 void BoxBulkStrainRateFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02668     modified[0] = modif::nothing;
02669     modified[1] = modif::staticVariables;
02670 }
02671 
02672 template<typename T, int nDim>
02673 BlockDomain::DomainT BoxBulkStrainRateFunctional2D<T,nDim>::appliesTo() const {
02674     return BlockDomain::bulkAndEnvelope;
02675 }
02676 
02677 
02678 template<typename T, int nDim>
02679 void BoxStrainRateFunctional2D<T,nDim>::processBulk (
02680         Box2D domain, TensorField2D<T,nDim>& velocity,
02681                       TensorField2D<T,SymmetricTensorImpl<T,nDim>::n>& S )
02682 {
02683     typedef SymmetricTensorImpl<T,nDim> tensor;
02684     Dot2D offset = computeRelativeDisplacement(velocity, S);
02685     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02686         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02687             plint iX2 = iX+offset.x;
02688             plint iY2 = iY+offset.y;
02689             Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2);
02690             el[tensor::xx] = fdDataField::bulkXderiv(velocity, iX, iY, 0);
02691             el[tensor::yy] = fdDataField::bulkYderiv(velocity, iX, iY, 1);
02692             el[tensor::xy] = ( fdDataField::bulkXderiv(velocity, iX, iY, 1) +
02693                                fdDataField::bulkYderiv(velocity, iX, iY, 0) ) / (T)2;
02694         }
02695     }
02696 }
02697 
02698 template<typename T, int nDim>
02699 void BoxStrainRateFunctional2D<T,nDim>::processEdge (
02700         int direction, int orientation, Box2D domain,
02701         TensorField2D<T,nDim>& velocity, TensorField2D<T,SymmetricTensorImpl<T,nDim>::n>& S )
02702 {
02703     typedef SymmetricTensorImpl<T,nDim> tensor;
02704     Dot2D offset = computeRelativeDisplacement(velocity, S);
02705     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02706         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02707             plint iX2 = iX+offset.x;
02708             plint iY2 = iY+offset.y;
02709             Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2);
02710             el[tensor::xx] = fdDataField::edgeXderiv(velocity, direction,orientation, iX, iY, 0);
02711             el[tensor::yy] = fdDataField::edgeYderiv(velocity, direction,orientation, iX, iY, 1);
02712             el[tensor::xy] = ( fdDataField::edgeXderiv(velocity, direction,orientation, iX, iY, 1) +
02713                                fdDataField::edgeYderiv(velocity, direction,orientation, iX, iY, 0) ) / (T)2;
02714         }
02715     }
02716 }
02717 
02718 template<typename T, int nDim>
02719 void BoxStrainRateFunctional2D<T,nDim>::processCorner (
02720         int normalX, int normalY,  Box2D domain,
02721         TensorField2D<T,nDim>& velocity, TensorField2D<T,SymmetricTensorImpl<T,nDim>::n>& S )
02722 {
02723     typedef SymmetricTensorImpl<T,nDim> tensor;
02724     Dot2D offset = computeRelativeDisplacement(velocity, S);
02725     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02726         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02727             plint iX2 = iX+offset.x;
02728             plint iY2 = iY+offset.y;
02729             Array<T,SymmetricTensorImpl<T,nDim>::n>& el = S.get(iX2,iY2);
02730             el[tensor::xx] = fdDataField::cornerXderiv(velocity, normalX,normalY, iX, iY, 0);
02731             el[tensor::yy] = fdDataField::cornerYderiv(velocity, normalX,normalY, iX, iY, 1);
02732             el[tensor::xy] = ( fdDataField::cornerXderiv(velocity, normalX,normalY, iX, iY, 1) +
02733                                fdDataField::cornerYderiv(velocity, normalX,normalY, iX, iY, 0) ) / (T)2;
02734         }
02735     }
02736 }
02737 
02738 template<typename T, int nDim>
02739 BoxStrainRateFunctional2D<T,nDim>* BoxStrainRateFunctional2D<T,nDim>::clone() const
02740 {
02741     return new BoxStrainRateFunctional2D<T,nDim>(*this);
02742 }
02743 
02744 template<typename T, int nDim>
02745 void BoxStrainRateFunctional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02746     modified[0] = modif::nothing;
02747     modified[1] = modif::staticVariables;
02748 }
02749 
02750 
02751 template<typename T, int nDim>
02752 BlockDomain::DomainT BoxStrainRateFunctional2D<T,nDim>::appliesTo() const {
02753     // Don't apply to envelope, because nearest neighbors need to be accessed.
02754     return BlockDomain::bulk;
02755 }
02756 
02757 
02758 /* ******** Tensor_A_plus_B_functional2D ************************************ */
02759 
02760 template<typename T, int nDim>
02761 void Tensor_A_plus_B_functional2D<T,nDim>::process (
02762         Box2D domain, std::vector<TensorField2D<T,nDim>*> fields )
02763 {
02764     PLB_PRECONDITION( fields.size()==3 );
02765     TensorField2D<T,nDim>& A = *fields[0];
02766     TensorField2D<T,nDim>& B = *fields[1];
02767     TensorField2D<T,nDim>& result = *fields[2];
02768     Dot2D offsetB      = computeRelativeDisplacement(A,B);
02769     Dot2D offsetResult = computeRelativeDisplacement(A,result);
02770     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02771         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02772             result.get(iX+offsetResult.x,iY+offsetResult.y)
02773                 = A.get(iX,iY) + B.get(iX+offsetB.x,iY+offsetB.y);
02774         }
02775     }
02776 }
02777 
02778 template<typename T, int nDim>
02779 Tensor_A_plus_B_functional2D<T,nDim>* Tensor_A_plus_B_functional2D<T,nDim>::clone() const {
02780     return new Tensor_A_plus_B_functional2D<T,nDim>(*this);
02781 }
02782 
02783 template<typename T, int nDim>
02784 void Tensor_A_plus_B_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02785     modified[0] = modif::nothing;
02786     modified[1] = modif::nothing;
02787     modified[2] = modif::staticVariables;
02788 }
02789 
02790 template<typename T, int nDim>
02791 BlockDomain::DomainT Tensor_A_plus_B_functional2D<T,nDim>::appliesTo() const {
02792     return BlockDomain::bulkAndEnvelope;
02793 }
02794 
02795 
02796 /* ******** Tensor_A_minus_B_functional2D ************************************ */
02797 
02798 template<typename T, int nDim>
02799 void Tensor_A_minus_B_functional2D<T,nDim>::process (
02800         Box2D domain, std::vector<TensorField2D<T,nDim>*> fields )
02801 {
02802     PLB_PRECONDITION( fields.size()==3 );
02803     TensorField2D<T,nDim>& A = *fields[0];
02804     TensorField2D<T,nDim>& B = *fields[1];
02805     TensorField2D<T,nDim>& result = *fields[2];
02806     Dot2D offsetB      = computeRelativeDisplacement(A,B);
02807     Dot2D offsetResult = computeRelativeDisplacement(A,result);
02808     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02809         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02810             result.get(iX+offsetResult.x,iY+offsetResult.y)
02811                 = A.get(iX,iY) - B.get(iX+offsetB.x,iY+offsetB.y);
02812         }
02813     }
02814 }
02815 
02816 template<typename T, int nDim>
02817 Tensor_A_minus_B_functional2D<T,nDim>* Tensor_A_minus_B_functional2D<T,nDim>::clone() const {
02818     return new Tensor_A_minus_B_functional2D<T,nDim>(*this);
02819 }
02820 
02821 template<typename T, int nDim>
02822 void Tensor_A_minus_B_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02823     modified[0] = modif::nothing;
02824     modified[1] = modif::nothing;
02825     modified[2] = modif::staticVariables;
02826 }
02827 
02828 template<typename T, int nDim>
02829 BlockDomain::DomainT Tensor_A_minus_B_functional2D<T,nDim>::appliesTo() const {
02830     return BlockDomain::bulkAndEnvelope;
02831 }
02832 
02833 
02834 /* ******** Tensor_A_times_B_functional2D ************************************ */
02835 
02836 template<typename T, int nDim>
02837 void Tensor_A_times_B_functional2D<T,nDim>::process (
02838         Box2D domain, std::vector<TensorField2D<T,nDim>*> fields )
02839 {
02840     PLB_PRECONDITION( fields.size()==3 );
02841     TensorField2D<T,nDim>& A = *fields[0];
02842     TensorField2D<T,nDim>& B = *fields[1];
02843     TensorField2D<T,nDim>& result = *fields[2];
02844     Dot2D offsetB      = computeRelativeDisplacement(A,B);
02845     Dot2D offsetResult = computeRelativeDisplacement(A,result);
02846     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02847         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02848             result.get(iX+offsetResult.x,iY+offsetResult.y)
02849                 = A.get(iX,iY) * B.get(iX+offsetB.x,iY+offsetB.y);
02850         }
02851     }
02852 }
02853 
02854 template<typename T, int nDim>
02855 Tensor_A_times_B_functional2D<T,nDim>* Tensor_A_times_B_functional2D<T,nDim>::clone() const {
02856     return new Tensor_A_times_B_functional2D<T,nDim>(*this);
02857 }
02858 
02859 template<typename T, int nDim>
02860 void Tensor_A_times_B_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02861     modified[0] = modif::nothing;
02862     modified[1] = modif::nothing;
02863     modified[2] = modif::staticVariables;
02864 }
02865 
02866 template<typename T, int nDim>
02867 BlockDomain::DomainT Tensor_A_times_B_functional2D<T,nDim>::appliesTo() const {
02868     return BlockDomain::bulkAndEnvelope;
02869 }
02870 
02871 
02872 /* ******** Tensor_A_dividedBy_B_functional2D ************************************ */
02873 
02874 template<typename T, int nDim>
02875 void Tensor_A_dividedBy_B_functional2D<T,nDim>::process (
02876         Box2D domain, std::vector<TensorField2D<T,nDim>*> fields )
02877 {
02878     PLB_PRECONDITION( fields.size()==3 );
02879     TensorField2D<T,nDim>& A = *fields[0];
02880     TensorField2D<T,nDim>& B = *fields[1];
02881     TensorField2D<T,nDim>& result = *fields[2];
02882     Dot2D offsetB      = computeRelativeDisplacement(A,B);
02883     Dot2D offsetResult = computeRelativeDisplacement(A,result);
02884     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02885         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02886             result.get(iX+offsetResult.x,iY+offsetResult.y)
02887                 = A.get(iX,iY) / B.get(iX+offsetB.x,iY+offsetB.y);
02888         }
02889     }
02890 }
02891 
02892 template<typename T, int nDim>
02893 Tensor_A_dividedBy_B_functional2D<T,nDim>* Tensor_A_dividedBy_B_functional2D<T,nDim>::clone() const {
02894     return new Tensor_A_dividedBy_B_functional2D<T,nDim>(*this);
02895 }
02896 
02897 template<typename T, int nDim>
02898 void Tensor_A_dividedBy_B_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02899     modified[0] = modif::nothing;
02900     modified[1] = modif::nothing;
02901     modified[2] = modif::staticVariables;
02902 }
02903 
02904 template<typename T, int nDim>
02905 BlockDomain::DomainT Tensor_A_dividedBy_B_functional2D<T,nDim>::appliesTo() const {
02906     return BlockDomain::bulkAndEnvelope;
02907 }
02908 
02909 
02910 /* ******** Tensor_A_plus_B_inplace_functional2D ************************************ */
02911 
02912 template<typename T, int nDim>
02913 void Tensor_A_plus_B_inplace_functional2D<T,nDim>::process (
02914         Box2D domain, TensorField2D<T,nDim>& A, TensorField2D<T,nDim>& B)
02915 {
02916     Dot2D offset = computeRelativeDisplacement(A,B);
02917     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02918         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02919             A.get(iX,iY) += B.get(iX+offset.x,iY+offset.y);
02920         }
02921     }
02922 }
02923 
02924 template<typename T, int nDim>
02925 Tensor_A_plus_B_inplace_functional2D<T,nDim>* Tensor_A_plus_B_inplace_functional2D<T,nDim>::clone() const {
02926     return new Tensor_A_plus_B_inplace_functional2D<T,nDim>(*this);
02927 }
02928 
02929 template<typename T, int nDim>
02930 void Tensor_A_plus_B_inplace_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02931     modified[0] = modif::staticVariables;
02932     modified[1] = modif::nothing;
02933 }
02934 
02935 template<typename T, int nDim>
02936 BlockDomain::DomainT Tensor_A_plus_B_inplace_functional2D<T,nDim>::appliesTo() const {
02937     return BlockDomain::bulkAndEnvelope;
02938 }
02939 
02940 
02941 /* ******** Tensor_A_minus_B_inplace_functional2D ************************************ */
02942 
02943 template<typename T, int nDim>
02944 void Tensor_A_minus_B_inplace_functional2D<T,nDim>::process (
02945         Box2D domain, TensorField2D<T,nDim>& A, TensorField2D<T,nDim>& B)
02946 {
02947     Dot2D offset = computeRelativeDisplacement(A,B);
02948     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02949         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02950             A.get(iX,iY) -= B.get(iX+offset.x,iY+offset.y);
02951         }
02952     }
02953 }
02954 
02955 template<typename T, int nDim>
02956 Tensor_A_minus_B_inplace_functional2D<T,nDim>* Tensor_A_minus_B_inplace_functional2D<T,nDim>::clone() const {
02957     return new Tensor_A_minus_B_inplace_functional2D<T,nDim>(*this);
02958 }
02959 
02960 template<typename T, int nDim>
02961 void Tensor_A_minus_B_inplace_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02962     modified[0] = modif::staticVariables;
02963     modified[1] = modif::nothing;
02964 }
02965 
02966 template<typename T, int nDim>
02967 BlockDomain::DomainT Tensor_A_minus_B_inplace_functional2D<T,nDim>::appliesTo() const {
02968     return BlockDomain::bulkAndEnvelope;
02969 }
02970 
02971 
02972 /* ******** Tensor_A_times_B_inplace_functional2D ************************************ */
02973 
02974 template<typename T, int nDim>
02975 void Tensor_A_times_B_inplace_functional2D<T,nDim>::process (
02976         Box2D domain, TensorField2D<T,nDim>& A, TensorField2D<T,nDim>& B)
02977 {
02978     Dot2D offset = computeRelativeDisplacement(A,B);
02979     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
02980         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
02981             A.get(iX,iY) *= B.get(iX+offset.x,iY+offset.y);
02982         }
02983     }
02984 }
02985 
02986 template<typename T, int nDim>
02987 Tensor_A_times_B_inplace_functional2D<T,nDim>* Tensor_A_times_B_inplace_functional2D<T,nDim>::clone() const {
02988     return new Tensor_A_times_B_inplace_functional2D<T,nDim>(*this);
02989 }
02990 
02991 template<typename T, int nDim>
02992 void Tensor_A_times_B_inplace_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
02993     modified[0] = modif::staticVariables;
02994     modified[1] = modif::nothing;
02995 }
02996 
02997 template<typename T, int nDim>
02998 BlockDomain::DomainT Tensor_A_times_B_inplace_functional2D<T,nDim>::appliesTo() const {
02999     return BlockDomain::bulkAndEnvelope;
03000 }
03001 
03002 
03003 /* ******** Tensor_A_times_alpha_inplace_functional2D ************************************ */
03004 
03005 template<typename T, int nDim>
03006 Tensor_A_times_alpha_inplace_functional2D<T,nDim>::
03007     Tensor_A_times_alpha_inplace_functional2D(T alpha_)
03008         : alpha(alpha_)
03009 { }
03010 
03011 template<typename T, int nDim>
03012 void Tensor_A_times_alpha_inplace_functional2D<T,nDim>::process (
03013         Box2D domain, TensorField2D<T,nDim>& A)
03014 {
03015     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03016         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03017             A.get(iX,iY) *= alpha;
03018         }
03019     }
03020 }
03021 
03022 template<typename T, int nDim>
03023 Tensor_A_times_alpha_inplace_functional2D<T,nDim>*
03024     Tensor_A_times_alpha_inplace_functional2D<T,nDim>::clone() const
03025 {
03026     return new Tensor_A_times_alpha_inplace_functional2D<T,nDim>(*this);
03027 }
03028 
03029 template<typename T, int nDim>
03030 void Tensor_A_times_alpha_inplace_functional2D<T,nDim>::
03031     getTypeOfModification(std::vector<modif::ModifT>& modified) const
03032 {
03033     modified[0] = modif::staticVariables;
03034 }
03035 
03036 template<typename T, int nDim>
03037 BlockDomain::DomainT Tensor_A_times_alpha_inplace_functional2D<T,nDim>::appliesTo() const {
03038     return BlockDomain::bulkAndEnvelope;
03039 }
03040 
03041 
03042 /* ******** Tensor_A_dividedBy_B_inplace_functional2D ************************************ */
03043 
03044 template<typename T, int nDim>
03045 void Tensor_A_dividedBy_B_inplace_functional2D<T,nDim>::process (
03046         Box2D domain, TensorField2D<T,nDim>& A, TensorField2D<T,nDim>& B)
03047 {
03048     Dot2D offset = computeRelativeDisplacement(A,B);
03049     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
03050         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
03051             A.get(iX,iY) /= B.get(iX+offset.x,iY+offset.y);
03052         }
03053     }
03054 }
03055 
03056 template<typename T, int nDim>
03057 Tensor_A_dividedBy_B_inplace_functional2D<T,nDim>* Tensor_A_dividedBy_B_inplace_functional2D<T,nDim>::clone() const {
03058     return new Tensor_A_dividedBy_B_inplace_functional2D<T,nDim>(*this);
03059 }
03060 
03061 template<typename T, int nDim>
03062 void Tensor_A_dividedBy_B_inplace_functional2D<T,nDim>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
03063     modified[0] = modif::staticVariables;
03064     modified[1] = modif::nothing;
03065 }
03066 
03067 template<typename T, int nDim>
03068 BlockDomain::DomainT Tensor_A_dividedBy_B_inplace_functional2D<T,nDim>::appliesTo() const {
03069     return BlockDomain::bulkAndEnvelope;
03070 }
03071 
03072 }  // namespace plb
03073 
03074 #endif  // DATA_ANALYSIS_FUNCTIONAL_2D_HH
03075