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

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