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

heLeeProcessor3D.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 
00025 /* This code was written with help of a Fortran code kindly provided
00026  * by Prof. Taehun Lee, and is massively co-authored by
00027  * Andrea Parmigiani.
00028  */
00029 
00030 #ifndef HE_LEE_PROCESSOR_3D_HH
00031 #define HE_LEE_PROCESSOR_3D_HH
00032 
00033 #include "heLeeProcessor3D.h"
00034 #include "latticeBoltzmann/momentTemplates.h"
00035 #include "latticeBoltzmann/geometricOperationTemplates.h"
00036 
00037 namespace plb {
00038 
00039    
00040 template<typename T>
00041 class FiniteDifference {
00042 public:
00043     FiniteDifference(ScalarField3D<T> const& field_,
00044                      plint x_, plint y_, plint z_ )
00045         : field(field_),
00046           x(x_), y(y_), z(z_)
00047     { }
00048     T val(plint iX, plint iY, plint iZ) const {
00049         return field.get(iX,iY,iZ);
00050     }
00051     void centralGradient(Array<T,3>& gradient) const {
00052         const T c1 = (T)2./(T)9.;
00053         const T c2 = (T)1./(T)18.;
00054         const T c3 = (T)1./(T)72.;
00055         gradient[0] =
00056                        ( val(x+1,y,z)   - val(x-1,y,z) ) *c1
00057                     +  ( val(x+1,y+1,z) - val(x-1,y-1,z)
00058                         +val(x+1,y-1,z) - val(x-1,y+1,z)
00059                         +val(x+1,y,z+1) - val(x-1,y,z-1)
00060                         +val(x+1,y,z-1) - val(x-1,y,z+1) ) *c2
00061                     +  ( val(x+1,y+1,z+1) - val(x-1,y-1,z-1)
00062                         +val(x+1,y-1,z+1) - val(x-1,y+1,z-1)
00063                         +val(x+1,y+1,z-1) - val(x-1,y-1,z+1)
00064                         +val(x+1,y-1,z-1) - val(x-1,y+1,z+1) ) *c3;
00065         gradient[1] =
00066                        ( val(x,y+1,z)   - val(x,y-1,z) ) *c1
00067                     +  ( val(x+1,y+1,z) - val(x-1,y-1,z)
00068                         +val(x-1,y+1,z) - val(x+1,y-1,z)
00069                         +val(x,y+1,z+1) - val(x,y-1,z-1)
00070                         +val(x,y+1,z-1) - val(x,y-1,z+1) ) *c2
00071                     +  ( val(x+1,y+1,z+1) - val(x-1,y-1,z-1)
00072                         +val(x+1,y+1,z-1) - val(x-1,y-1,z+1)
00073                         +val(x-1,y+1,z+1) - val(x+1,y-1,z-1)
00074                         +val(x-1,y+1,z-1) - val(x+1,y-1,z+1) ) *c3;
00075         gradient[2] =
00076                        ( val(x,y,z+1)   - val(x,y,z-1) ) *c1
00077                     +  ( val(x+1,y,z+1) - val(x-1,y,z-1)
00078                         +val(x-1,y,z+1) - val(x+1,y,z-1)
00079                         +val(x,y+1,z+1) - val(x,y-1,z-1)
00080                         +val(x,y-1,z+1) - val(x,y+1,z-1) ) *c2
00081                     +  ( val(x+1,y+1,z+1) - val(x-1,y-1,z-1)
00082                         +val(x+1,y-1,z+1) - val(x-1,y+1,z-1)
00083                         +val(x-1,y+1,z+1) - val(x+1,y-1,z-1)
00084                         +val(x-1,y-1,z+1) - val(x+1,y+1,z-1) ) *c3;
00085     }
00086     void biasedGradient(Array<T,3>& gradient) const {
00087         const T c1 = (T)1./(T)9.;
00088         const T c2 = (T)1./(T)36.;
00089         const T c3 = (T)1./(T)144.;
00090         gradient[0] =
00091                        (    -val(x+2,y,z) + 4.*val(x+1,y,z)
00092                          -4.*val(x-1,y,z) +    val(x-2,y,z) ) *c1
00093                       +(    -val(x+2,y+2,z) + 4.*val(x+1,y+1,z)
00094                          -4.*val(x-1,y-1,z) +    val(x-2,y-2,z)
00095                             -val(x+2,y-2,z) + 4.*val(x+1,y-1,z)
00096                          -4.*val(x-1,y+1,z) +    val(x-2,y+2,z)
00097                             -val(x+2,y,z+2) + 4.*val(x+1,y,z+1)
00098                          -4.*val(x-1,y,z-1) +    val(x-2,y,z-2)
00099                             -val(x+2,y,z-2) + 4.*val(x+1,y,z-1)
00100                          -4.*val(x-1,y,z+1) +    val(x-2,y,z+2) ) *c2
00101                       +(    -val(x+2,y+2,z+2) + 4.*val(x+1,y+1,z+1)
00102                          -4.*val(x-1,y-1,z-1) +    val(x-2,y-2,z-2)
00103                             -val(x+2,y-2,z+2) + 4.*val(x+1,y-1,z+1)
00104                          -4.*val(x-1,y+1,z-1) +    val(x-2,y+2,z-2)
00105                             -val(x+2,y+2,z-2) + 4.*val(x+1,y+1,z-1)
00106                          -4.*val(x-1,y-1,z+1) +    val(x-2,y-2,z+2)
00107                             -val(x+2,y-2,z-2) + 4.*val(x+1,y-1,z-1)
00108                          -4.*val(x-1,y+1,z+1) +    val(x-2,y+2,z+2) ) *c3;
00109         gradient[1] =
00110                        (    -val(x,y+2,z) + 4.*val(x,y+1,z)
00111                          -4.*val(x,y-1,z) +    val(x,y-2,z) ) *c1
00112                       +(    -val(x+2,y+2,z) + 4.*val(x+1,y+1,z)
00113                          -4.*val(x-1,y-1,z) +    val(x-2,y-2,z)
00114                             -val(x-2,y+2,z) + 4.*val(x-1,y+1,z)
00115                          -4.*val(x+1,y-1,z) +    val(x+2,y-2,z)
00116                             -val(x,y+2,z+2) + 4.*val(x,y+1,z+1)
00117                          -4.*val(x,y-1,z-1) +    val(x,y-2,z-2)
00118                             -val(x,y+2,z-2) + 4.*val(x,y+1,z-1)
00119                          -4.*val(x,y-1,z+1) +    val(x,y-2,z+2) ) *c2
00120                       +(    -val(x+2,y+2,z+2) + 4.*val(x+1,y+1,z+1)
00121                          -4.*val(x-1,y-1,z-1) +    val(x-2,y-2,z-2)
00122                             -val(x+2,y+2,z-2) + 4.*val(x+1,y+1,z-1)
00123                          -4.*val(x-1,y-1,z+1) +    val(x-2,y-2,z+2)
00124                             -val(x-2,y+2,z+2) + 4.*val(x-1,y+1,z+1)
00125                          -4.*val(x+1,y-1,z-1) +    val(x+2,y-2,z-2)
00126                             -val(x-2,y+2,z-2) + 4.*val(x-1,y+1,z-1)
00127                          -4.*val(x+1,y-1,z+1) +    val(x+2,y-2,z+2) ) *c3;
00128         gradient[2] =
00129                         (    -val(x,y,z+2) + 4.*val(x,y,z+1)
00130                           -4.*val(x,y,z-1) +    val(x,y,z-2) ) *c1
00131                        +(    -val(x+2,y,z+2) + 4.*val(x+1,y,z+1)
00132                           -4.*val(x-1,y,z-1) +    val(x-2,y,z-2)
00133                              -val(x-2,y,z+2) + 4.*val(x-1,y,z+1)
00134                           -4.*val(x+1,y,z-1) +    val(x+2,y,z-2)
00135                              -val(x,y+2,z+2) + 4.*val(x,y+1,z+1)
00136                           -4.*val(x,y-1,z-1) +    val(x,y-2,z-2)
00137                              -val(x,y-2,z+2) + 4.*val(x,y-1,z+1)
00138                           -4.*val(x,y+1,z-1) +    val(x,y+2,z-2) ) *c2
00139                        +(    -val(x+2,y+2,z+2) + 4.*val(x+1,y+1,z+1)
00140                           -4.*val(x-1,y-1,z-1) +    val(x-2,y-2,z-2)
00141                              -val(x+2,y-2,z+2) + 4.*val(x+1,y-1,z+1)
00142                           -4.*val(x-1,y+1,z-1) +    val(x-2,y+2,z-2)
00143                              -val(x-2,y+2,z+2) + 4.*val(x-1,y+1,z+1)
00144                           -4.*val(x+1,y-1,z-1) +    val(x+2,y-2,z-2)
00145                              -val(x-2,y-2,z+2) + 4.*val(x-1,y-1,z+1)
00146                           -4.*val(x+1,y+1,z-1) +    val(x+2,y+2,z-2) ) *c3;
00147     }
00148 
00149     T laplacian() const
00150     {
00151         static const T c1 = (T)4./(T)9.;
00152         static const T c2 = (T)1./(T)9.;
00153         static const T c3 = (T)1./(T)36.;
00154         static const T c4 = (T)38/(T)9.;
00155 
00156         return
00157             ( val(x+1,y,z)+val(x-1,y,z)
00158              +val(x,y+1,z)+val(x,y-1,z)
00159              +val(x,y,z+1)+val(x,y,z-1) ) *c1
00160            +( val(x+1,y+1,z)+val(x-1,y-1,z)
00161              +val(x+1,y-1,z)+val(x-1,y+1,z)
00162              +val(x+1,y,z+1)+val(x-1,y,z-1)
00163              +val(x+1,y,z-1)+val(x-1,y,z+1)
00164              +val(x,y+1,z+1)+val(x,y-1,z-1)
00165              +val(x,y+1,z-1)+val(x,y-1,z+1) ) *c2
00166            +( val(x+1,y+1,z+1)+val(x+1,y+1,z-1)
00167              +val(x+1,y-1,z+1)+val(x+1,y-1,z-1)
00168              +val(x-1,y+1,z+1)+val(x-1,y+1,z-1)
00169              +val(x-1,y-1,z+1)+val(x-1,y-1,z-1) ) *c3
00170            -val(x,y,z) *c4;
00171     }
00172 
00173 private:
00174     ScalarField3D<T> const& field;
00175     plint x,y,z;
00176 };
00177 
00178 
00179 /* *************** Compute_C_processor ***************** */
00180 
00181 template<typename T, template<typename U> class Descriptor >
00182 Compute_C_processor <T,Descriptor>::Compute_C_processor(T M_)
00183     : M(M_)
00184 { }
00185 
00186 template<typename T, template<typename U> class Descriptor >
00187 void Compute_C_processor<T,Descriptor>::processGenericBlocks (
00188         Box3D domain, std::vector<AtomicBlock3D*> blocks )
00189 {
00190     BlockLattice3D<T,Descriptor>& f = *dynamic_cast<BlockLattice3D<T,Descriptor>*>(blocks[0]);
00191     // Laplacian of chemical potential at previous time step t-1.
00192     ScalarField3D<T>& laplaceMu     = *dynamic_cast<ScalarField3D<T>*>(blocks[1]);
00193     ScalarField3D<T>& C             = *dynamic_cast<ScalarField3D<T>*>(blocks[2]);
00194     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00195         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00196             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00197                                   // Use templates to compute order-0 moment of f.
00198                 C.get(iX,iY,iZ) = momentTemplates<T,Descriptor>::get_rhoBar(f.get(iX,iY,iZ))
00199                                   + 0.5 * M * laplaceMu.get(iX,iY,iZ);
00200             }
00201         }
00202     }
00203 }
00204 
00205 
00206 template<typename T, template<typename U> class Descriptor >
00207 Compute_C_processor<T,Descriptor>*
00208     Compute_C_processor<T,Descriptor>::clone() const
00209 {
00210     return new Compute_C_processor<T,Descriptor>(*this);
00211 }
00212 
00213 template<typename T, template<typename U> class Descriptor >
00214 void Compute_C_processor<T,Descriptor>::getTypeOfModification (
00215         std::vector<modif::ModifT>& modified ) const
00216 {
00217     modified[0] = modif::nothing; // f
00218     modified[1] = modif::nothing; // laplaceMu(t-1)
00219     modified[2] = modif::staticVariables;  // C
00220 }
00221 
00222 
00223 /* *************** Compute_gradC_rho_mu_processor ***************** */
00224 
00225 template<typename T>
00226 Compute_gradC_rho_mu_processor<T>::Compute_gradC_rho_mu_processor (
00227         T beta_, T kappa_, T rho_h_, T rho_l_ )
00228     : beta(beta_),
00229       kappa(kappa_),
00230       rho_h(rho_h_),
00231       rho_l(rho_l_)
00232 { }
00233 
00234 template<typename T>
00235 void Compute_gradC_rho_mu_processor<T>::processGenericBlocks (
00236         Box3D domain, std::vector<AtomicBlock3D*> blocks )
00237 {
00238     // blocks[0] stands for the unused f.
00239     ScalarField3D<T>& C       = *dynamic_cast<ScalarField3D<T>*>(blocks[1]);
00240     TensorField3D<T,3>& gradC = *dynamic_cast<TensorField3D<T,3>*>(blocks[2]);
00241     ScalarField3D<T>& rho     = *dynamic_cast<ScalarField3D<T>*>(blocks[3]);
00242     ScalarField3D<T>& mu      = *dynamic_cast<ScalarField3D<T>*>(blocks[4]);
00243 
00244     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00245         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00246             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00247                 FiniteDifference<T>(C,iX,iY,iZ).centralGradient(gradC.get(iX,iY,iZ));
00248                 T C_ = C.get(iX,iY,iZ);
00249                 rho.get(iX,iY,iZ) = C_ * (rho_h-rho_l) + rho_l;
00250                 mu.get(iX,iY,iZ) = 4.*beta*C_*(C_-0.5)*(C_-1.) -
00251                                    kappa*FiniteDifference<T>(C,iX,iY,iZ).laplacian();
00252             }
00253         }
00254     }
00255 }
00256 
00257 
00258 template<typename T>
00259 Compute_gradC_rho_mu_processor<T>*
00260     Compute_gradC_rho_mu_processor<T>::clone() const
00261 {
00262     return new Compute_gradC_rho_mu_processor<T>(*this);
00263 }
00264 
00265 template<typename T>
00266 void Compute_gradC_rho_mu_processor<T>::getTypeOfModification (
00267         std::vector<modif::ModifT>& modified ) const
00268 {
00269     modified[0] = modif::nothing;  // f
00270     modified[1] = modif::nothing;  // C
00271     modified[2] = modif::staticVariables;   // gradC
00272     modified[3] = modif::staticVariables;   // rho
00273     modified[4] = modif::staticVariables;   // mu
00274 }
00275 
00276 
00277 /* *************** Compute_gradMu_laplaceMu_processor ***************** */
00278 
00279 template<typename T, template<typename U> class Descriptor >
00280 Compute_gradMu_laplaceMu_processor <T,Descriptor>::Compute_gradMu_laplaceMu_processor()
00281 { }
00282 
00283 template<typename T, template<typename U> class Descriptor >
00284 void Compute_gradMu_laplaceMu_processor<T,Descriptor>::processGenericBlocks (
00285         Box3D domain, std::vector<AtomicBlock3D*> blocks )
00286 {
00287     // blocks[0] stands for the unused f.
00288     ScalarField3D<T>& mu            = *dynamic_cast<ScalarField3D<T>*>(blocks[1]);
00289     TensorField3D<T,3>& gradMu      = *dynamic_cast<TensorField3D<T,3>*>(blocks[2]);
00290     ScalarField3D<T>& laplaceMu     = *dynamic_cast<ScalarField3D<T>*>(blocks[3]);
00291 
00292     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00293         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00294             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00295                 FiniteDifference<T>(mu,iX,iY,iZ).centralGradient(gradMu.get(iX,iY,iZ));
00296                 laplaceMu.get(iX,iY,iZ) = FiniteDifference<T>(mu,iX,iY,iZ).laplacian();
00297             }
00298         }
00299     }
00300 }
00301 
00302 
00303 template<typename T, template<typename U> class Descriptor >
00304 Compute_gradMu_laplaceMu_processor<T,Descriptor>*
00305     Compute_gradMu_laplaceMu_processor<T,Descriptor>::clone() const
00306 {
00307     return new Compute_gradMu_laplaceMu_processor<T,Descriptor>(*this);
00308 }
00309 
00310 template<typename T, template<typename U> class Descriptor >
00311 void Compute_gradMu_laplaceMu_processor<T,Descriptor>::getTypeOfModification (
00312         std::vector<modif::ModifT>& modified ) const
00313 {
00314     modified[0] = modif::nothing;  // f
00315     modified[1] = modif::nothing;  // mu
00316     modified[2] = modif::staticVariables;   // gradMu
00317     modified[3] = modif::staticVariables;   // laplaceMu
00318 }
00319 
00320 
00321 /* *************** Compute_gradMu_laplaceMu_u_p1_processor ***************** */
00322 
00323 template<typename T, template<typename U> class Descriptor >
00324 Compute_gradMu_laplaceMu_u_p1_processor <T,Descriptor>::Compute_gradMu_laplaceMu_u_p1_processor (
00325         T rho_h_, T rho_l_, T RT_ )
00326     : rho_h(rho_h_),
00327       rho_l(rho_l_),
00328       RT(RT_)
00329 { }
00330 
00331 template<typename T, template<typename U> class Descriptor >
00332 void Compute_gradMu_laplaceMu_u_p1_processor<T,Descriptor>::processGenericBlocks (
00333         Box3D domain, std::vector<AtomicBlock3D*> blocks )
00334 {
00335     // blocks[0] stands for the unused f.
00336     BlockLattice3D<T,Descriptor>& g = *dynamic_cast<BlockLattice3D<T,Descriptor>*>(blocks[1]);
00337     ScalarField3D<T>& C             = *dynamic_cast<ScalarField3D<T>*>(blocks[2]);
00338     ScalarField3D<T>& rho           = *dynamic_cast<ScalarField3D<T>*>(blocks[3]);
00339     TensorField3D<T,3>& gradC       = *dynamic_cast<TensorField3D<T,3>*>(blocks[4]);
00340     ScalarField3D<T>& mu            = *dynamic_cast<ScalarField3D<T>*>(blocks[5]);
00341     TensorField3D<T,3>& gradMu      = *dynamic_cast<TensorField3D<T,3>*>(blocks[6]);
00342     ScalarField3D<T>& laplaceMu     = *dynamic_cast<ScalarField3D<T>*>(blocks[7]);
00343     TensorField3D<T,3>& u           = *dynamic_cast<TensorField3D<T,3>*>(blocks[8]);
00344     ScalarField3D<T>& p1            = *dynamic_cast<ScalarField3D<T>*>(blocks[9]);
00345 
00346     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00347         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00348             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00349                 Array<T,3>& u_      = u.get(iX,iY,iZ);
00350                 Array<T,3>& gradMu_ = gradMu.get(iX,iY,iZ);
00351                 Array<T,3>& gradC_  = gradC.get(iX,iY,iZ);
00352                 T invRho            = (T)1 / rho.get(iX,iY,iZ);
00353 
00354                 FiniteDifference<T>(mu,iX,iY,iZ).centralGradient(gradMu_);
00355                 laplaceMu.get(iX,iY,iZ) = FiniteDifference<T>(mu,iX,iY,iZ).laplacian();
00356                 // Use templates to compute order-0 and order-1 moment of g.
00357                 momentTemplates<T,Descriptor>::get_rhoBar_j (
00358                         g.get(iX,iY,iZ), p1.get(iX,iY,iZ), u_);
00359                 u_ *= invRho/RT;
00360                 u_ -= gradMu_ * ( 0.5*invRho*C.get(iX,iY,iZ) );
00361                 p1.get(iX,iY,iZ) +=
00362                      0.5*RT * (rho_h-rho_l)
00363                          * VectorTemplateImpl<T,3>::scalarProduct(u_, gradC_);
00364             }
00365         }
00366     }
00367 }
00368 
00369 
00370 template<typename T, template<typename U> class Descriptor >
00371 Compute_gradMu_laplaceMu_u_p1_processor<T,Descriptor>*
00372     Compute_gradMu_laplaceMu_u_p1_processor<T,Descriptor>::clone() const
00373 {
00374     return new Compute_gradMu_laplaceMu_u_p1_processor<T,Descriptor>(*this);
00375 }
00376 
00377 template<typename T, template<typename U> class Descriptor >
00378 void Compute_gradMu_laplaceMu_u_p1_processor<T,Descriptor>::getTypeOfModification (
00379         std::vector<modif::ModifT>& modified ) const
00380 {
00381     modified[0] = modif::nothing;  // f
00382     modified[1] = modif::nothing;  // g
00383     modified[2] = modif::nothing;  // C
00384     modified[3] = modif::nothing;  // rho
00385     modified[4] = modif::nothing;  // gradC
00386     modified[5] = modif::nothing;  // mu
00387     modified[6] = modif::staticVariables;   // gradMu
00388     modified[7] = modif::staticVariables;   // laplaceMu
00389     modified[8] = modif::staticVariables;   // u
00390     modified[9] = modif::staticVariables;   // p1
00391 }
00392 
00393 
00394 /* *************** HeLeeCollisionProcessor ***************** */
00395 
00396 template<typename T, template<typename U> class Descriptor >
00397 HeLeeCollisionProcessor <T,Descriptor>::HeLeeCollisionProcessor (
00398         T rho_h_, T rho_l_, T tau_h_, T tau_l_, T M_, T RT_,
00399         bool initialize_ )
00400     : rho_h(rho_h_),
00401       rho_l(rho_l_),
00402       tau_h(tau_h_),
00403       tau_l(tau_l_),
00404       M(M_),
00405       RT(RT_),
00406       initialize(initialize_)
00407 { }
00408 
00409 template<typename T, template<typename U> class Descriptor >
00410 void HeLeeCollisionProcessor<T,Descriptor>::computeAdvectionTerms (
00411         ScalarField3D<T> const& C, T& adv_gradC, T& bias_adv_gradC,
00412         plint iX, plint iY, plint iZ, plint iPop )
00413 {
00414     typedef Descriptor<T> D;
00415     T diff_p2 = C.get(iX+2*D::c[iPop][0], iY+2*D::c[iPop][1], iZ+2*D::c[iPop][2]) -
00416                 C.get(iX+D::c[iPop][0], iY+D::c[iPop][1], iZ+D::c[iPop][2]);
00417     T diff_p1 = C.get(iX+D::c[iPop][0], iY+D::c[iPop][1], iZ+D::c[iPop][2]) -
00418                 C.get(iX, iY, iZ);
00419     T diff_p0 = C.get(iX, iY, iZ) -
00420                 C.get(iX-D::c[iPop][0], iY-D::c[iPop][1], iZ-D::c[iPop][2]);
00421     adv_gradC = diff_p1 - 0.5*(diff_p1-diff_p0);
00422     bias_adv_gradC = diff_p1 - 0.25*(diff_p2-diff_p0);
00423 }
00424 
00425 template<typename T, template<typename U> class Descriptor >
00426 void HeLeeCollisionProcessor<T,Descriptor>::processGenericBlocks (
00427         Box3D domain, std::vector<AtomicBlock3D*> blocks )
00428 {
00429     typedef Descriptor<T> D;
00430     BlockLattice3D<T,Descriptor>& f = *dynamic_cast<BlockLattice3D<T,Descriptor>*>(blocks[0]);
00431     BlockLattice3D<T,Descriptor>& g = *dynamic_cast<BlockLattice3D<T,Descriptor>*>(blocks[1]);
00432     ScalarField3D<T>& C             = *dynamic_cast<ScalarField3D<T>*>(blocks[2]);
00433     ScalarField3D<T>& rho           = *dynamic_cast<ScalarField3D<T>*>(blocks[3]);
00434     TensorField3D<T,3>& gradC       = *dynamic_cast<TensorField3D<T,3>*>(blocks[4]);
00435     ScalarField3D<T>& mu            = *dynamic_cast<ScalarField3D<T>*>(blocks[5]);
00436     TensorField3D<T,3>& gradMu      = *dynamic_cast<TensorField3D<T,3>*>(blocks[6]);
00437     ScalarField3D<T>& laplaceMu     = *dynamic_cast<ScalarField3D<T>*>(blocks[7]);
00438     TensorField3D<T,3>& u           = *dynamic_cast<TensorField3D<T,3>*>(blocks[8]);
00439     ScalarField3D<T>& p1            = *dynamic_cast<ScalarField3D<T>*>(blocks[9]);
00440 
00441     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00442         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00443             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00444                 Array<T,3>& u_ = u.get(iX,iY,iZ);
00445                 T& C_ = C.get(iX,iY,iZ);
00446                 T& rho_ = rho.get(iX,iY,iZ);
00447                 T& laplaceMu_ = laplaceMu.get(iX,iY,iZ);
00448                 T& p1_ = p1.get(iX,iY,iZ);
00449                 Cell<T,Descriptor>& f_ = f.get(iX,iY,iZ);
00450                 Cell<T,Descriptor>& g_ = g.get(iX,iY,iZ);
00451 
00452                 T tau = C_*(tau_h-tau_l) + tau_l;
00453 
00454                 Array<T,3> biasGradC, biasGradMu, gradP, biasGradP;
00455                 FiniteDifference<T>(C,iX,iY,iZ).biasedGradient(biasGradC);
00456                 FiniteDifference<T>(mu,iX,iY,iZ).biasedGradient(biasGradMu);
00457                 FiniteDifference<T>(p1,iX,iY,iZ).centralGradient(gradP);
00458                 FiniteDifference<T>(p1,iX,iY,iZ).biasedGradient(biasGradP);
00459 
00460                 T uGradC =
00461                     VectorTemplateImpl<T,3>::scalarProduct(u_, gradC.get(iX,iY,iZ));
00462                 T uBiasGradC =
00463                     VectorTemplateImpl<T,3>::scalarProduct(u_, biasGradC);
00464                 T uGradMu =
00465                     VectorTemplateImpl<T,3>::scalarProduct(u_, gradMu.get(iX,iY,iZ));
00466                 T uBiasGradMu =
00467                     VectorTemplateImpl<T,3>::scalarProduct(u_, biasGradMu);
00468                 T uGradP =
00469                     VectorTemplateImpl<T,3>::scalarProduct(u_, gradP);
00470                 T uBiasGradP =
00471                     VectorTemplateImpl<T,3>::scalarProduct(u_, biasGradP);
00472                 T uSqr =
00473                     VectorTemplateImpl<T,3>::normSqr(u_);
00474                 for (plint iPop=0; iPop<Descriptor<T>::q; ++iPop) {
00475                     T ci_u = D::c[iPop][0]*u_[0]+D::c[iPop][1]*u_[1]+D::c[iPop][2]*u_[2];
00476                     T ti = Descriptor<T>::t[iPop];
00477                     T gamma0 = ti;
00478                     T gammaBar = 3.*ci_u + 4.5*ci_u*ci_u - 1.5*uSqr;
00479                     T gamma = ti*(1.+gammaBar);
00480 
00481                     T adv_gradC, bias_adv_gradC;
00482                     computeAdvectionTerms(C, adv_gradC, bias_adv_gradC, iX,iY,iZ,iPop);
00483                     adv_gradC -= uGradC;
00484                     bias_adv_gradC -= uBiasGradC;
00485 
00486                     T adv_gradP, bias_adv_gradP;
00487                     computeAdvectionTerms(p1, adv_gradP, bias_adv_gradP, iX,iY,iZ,iPop);
00488                     adv_gradP -= uGradP;
00489                     bias_adv_gradP -= uBiasGradP;
00490 
00491                     T adv_gradMu, bias_adv_gradMu;
00492                     computeAdvectionTerms(mu, adv_gradMu, bias_adv_gradMu, iX,iY,iZ,iPop);
00493                     adv_gradMu -= uGradMu;
00494                     adv_gradMu *= C_;
00495                     bias_adv_gradMu -= uBiasGradMu;
00496                     bias_adv_gradMu *= C_;
00497 
00498                     T fieq = ti * C_*(1+gammaBar)
00499                                  - 0.5*gamma*(adv_gradC-1./RT*(adv_gradP+adv_gradMu)*C_/rho_)
00500                                  - 0.5*gamma*M*laplaceMu_;
00501 
00502                     T gieq = ti*(p1_+rho_*RT*gammaBar)
00503                                  - 0.5*RT*adv_gradC*(rho_h-rho_l)*(gamma-gamma0)
00504                                  + 0.5*gamma*adv_gradMu;
00505                     if (initialize) {
00506                         f_[iPop] = fieq;
00507                         g_[iPop] = gieq;
00508                     }
00509                     else {
00510                         f_[iPop] += -(f_[iPop]-fieq)* 1./(tau+0.5) 
00511                                     +gamma* (
00512                                          bias_adv_gradC-(bias_adv_gradP+bias_adv_gradMu)*1./RT*C_/rho_ )
00513                                     + M*laplaceMu_*gamma;
00514                         g_[iPop] += -(g_[iPop]-gieq)* 1./(tau+0.5) 
00515                                     + bias_adv_gradC*(rho_h-rho_l)*RT*(gamma-gamma0)-bias_adv_gradMu*gamma;
00516                     }
00517                 }
00518             }
00519         }
00520     }
00521 }
00522 
00523 
00524 template<typename T, template<typename U> class Descriptor >
00525 HeLeeCollisionProcessor<T,Descriptor>*
00526     HeLeeCollisionProcessor<T,Descriptor>::clone() const
00527 {
00528     return new HeLeeCollisionProcessor<T,Descriptor>(*this);
00529 }
00530 
00531 template<typename T, template<typename U> class Descriptor >
00532 void HeLeeCollisionProcessor<T,Descriptor>::getTypeOfModification (
00533         std::vector<modif::ModifT>& modified ) const
00534 {
00535     modified[0] = modif::staticVariables;   // f
00536     modified[1] = modif::staticVariables;   // g
00537     modified[2] = modif::nothing;  // C
00538     modified[3] = modif::nothing;  // rho
00539     modified[4] = modif::nothing;  // gradC
00540     modified[5] = modif::nothing;  // mu
00541     modified[6] = modif::nothing;  // gradMu
00542     modified[7] = modif::nothing;  // laplaceMu
00543     modified[8] = modif::nothing;  // u
00544     modified[9] = modif::nothing;  // p1
00545 }
00546 
00547 }  // namespace plb
00548 
00549 #endif  // HE_LEE_PROCESSOR_3D_HH