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

dynamicsTemplates3D.h

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 
00029 #ifndef DYNAMICS_TEMPLATES_3D_H
00030 #define DYNAMICS_TEMPLATES_3D_H
00031 
00032 #include "core/globalDefs.h"
00033 #include "latticeBoltzmann/nearestNeighborLattices3D.h"
00034 #include "latticeBoltzmann/geometricOperationTemplates.h"
00035 
00036 namespace plb {
00037 
00038 template<typename T>
00039 struct neqPiD3Q27 {
00040 
00041     typedef SymmetricTensorImpl<T,3> S;
00042 
00043     static T fromPiToFneq0(Array<T,6> const& pi) {
00044         return (T)4/(T)3 * (
00045                  -(T)1/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00046                );
00047     }
00048 
00049     static T fromPiToFneq1(Array<T,6> const& pi) {
00050         return (T)1/(T)3 * (
00051                   (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00052                );
00053     }
00054 
00055     static T fromPiToFneq2(Array<T,6> const& pi) {
00056         return (T)1/(T)3 * (
00057                   -(T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00058                );
00059     }
00060 
00061     static T fromPiToFneq3(Array<T,6> const& pi) {
00062         return (T)1/(T)3 * (
00063                   -(T)1/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00064                );
00065     }
00066 
00067     static T fromPiToFneq4(Array<T,6> const& pi) {
00068         return (T)1/(T)12 * (
00069                   (T)2 * pi[S::xy]
00070                   + (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00071                );
00072     }
00073 
00074     static T fromPiToFneq5(Array<T,6> const& pi) {
00075         return (T)1/(T)12 * (
00076                   - (T)2 * pi[S::xy]
00077                   + (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00078                );
00079     }
00080 
00081     static T fromPiToFneq6(Array<T,6> const& pi) {
00082         return (T)1/(T)12 * (
00083                   (T)2 * pi[S::xz]
00084                   + (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00085                );
00086     }
00087 
00088     static T fromPiToFneq7(Array<T,6> const& pi) {
00089         return (T)1/(T)12 * (
00090                   - (T)2 * pi[S::xz]
00091                   + (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00092                );
00093     }
00094 
00095     static T fromPiToFneq8(Array<T,6> const& pi) {
00096         return (T)1/(T)12 * (
00097                   (T)2 * pi[S::yz]
00098                   - (T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00099                );
00100     }
00101 
00102     static T fromPiToFneq9(Array<T,6> const& pi) {
00103         return (T)1/(T)12 * (
00104                   - (T)2 * pi[S::yz]
00105                   - (T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00106                );
00107     }
00108 
00109     static T fromPiToFneq10(Array<T,6> const& pi) {
00110         return (T)1/(T)48 * (
00111                   + (T)2*pi[S::xy] + (T)2*pi[S::xz] + (T)2*pi[S::yz]
00112                   + (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00113                );
00114     }
00115 
00116     static T fromPiToFneq11(Array<T,6> const& pi) {
00117         return (T)1/(T)48 * (
00118                   + (T)2*pi[S::xy] - (T)2*pi[S::xz] - (T)2*pi[S::yz]
00119                   + (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00120                );
00121     }
00122 
00123     static T fromPiToFneq12(Array<T,6> const& pi) {
00124         return (T)1/(T)48 * (
00125                   - (T)2*pi[S::xy] + (T)2*pi[S::xz] - (T)2*pi[S::yz]
00126                   + (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00127                );
00128     }
00129 
00130     static T fromPiToFneq13(Array<T,6> const& pi) {
00131         return (T)1/(T)48 * (
00132                   - (T)2*pi[S::xy] - (T)2*pi[S::xz] + (T)2*pi[S::yz]
00133                   + (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00134                );
00135     }
00136 
00137 };
00138 
00139 // Efficient specialization for D3Q27 lattice
00140 template<typename T>
00141 struct dynamicsTemplatesImpl<T, descriptors::D3Q27DescriptorBase<T> > {
00142 
00143 typedef descriptors::D3Q27DescriptorBase<T> Descriptor;
00144 
00145 static T bgk_ma2_equilibrium(plint iPop, T rhoBar, T invRho, Array<T,3> const& j, T jSqr ) {
00146     T c_j = Descriptor::c[iPop][0]*j[0] + Descriptor::c[iPop][1]*j[1] + Descriptor::c[iPop][2]*j[2];
00147     return Descriptor::t[iPop] * ( rhoBar + 3.*c_j + invRho*(4.5*c_j*c_j - 1.5*jSqr) );
00148 }
00149 
00150 static void bgk_ma2_equilibria( T rhoBar, T invRho, Array<T,Descriptor::d> const& j,
00151                                 T jSqr, Array<T,Descriptor::q>& eqPop )
00152 {
00153     T t0 = Descriptor::t[0];
00154     T t1 = Descriptor::t[1];
00155     T t4 = Descriptor::t[4];
00156     T t10 = Descriptor::t[10];
00157 
00158     T kx     = (T)3 * j[0];
00159     T ky     = (T)3 * j[1];
00160     T kz     = (T)3 * j[2];
00161     T kxSqr_ = invRho / (T)2 * kx*kx;
00162     T kySqr_ = invRho / (T)2 * ky*ky;
00163     T kzSqr_ = invRho / (T)2 * kz*kz;
00164     T kxky_  = invRho * kx*ky;
00165     T kxkz_  = invRho * kx*kz;
00166     T kykz_  = invRho * ky*kz;
00167 
00168     T C1 = rhoBar + invRho*(T)3*jSqr;
00169     T C2, C3;
00170 
00171     // i=0
00172     C3 = -kxSqr_ - kySqr_ - kzSqr_;
00173     eqPop[0] = t0 * (C1+C3);
00174 
00175     // i=1 and i=14
00176     C2 = -kx;
00177     C3 = -kySqr_ - kzSqr_;
00178     eqPop[1]  = t1 * (C1+C2+C3);
00179     eqPop[14] = t1 * (C1-C2+C3);
00180 
00181     // i=2 and i=15
00182     C2 = -ky;
00183     C3 = -kxSqr_ - kzSqr_;
00184     eqPop[2]  = t1 * (C1+C2+C3);
00185     eqPop[15] = t1 * (C1-C2+C3);
00186 
00187     // i=3 and i=16
00188     C2 = -kz;
00189     C3 = -kxSqr_ - kySqr_;
00190     eqPop[3]  = t1 * (C1+C2+C3);
00191     eqPop[16] = t1 * (C1-C2+C3);
00192 
00193     // i=4 and i=17
00194     C2 = -kx - ky;
00195     C3 = kxky_ - kzSqr_;
00196     eqPop[4]  = t4 * (C1+C2+C3);
00197     eqPop[17] = t4 * (C1-C2+C3);
00198 
00199     // i=5 and i=18
00200     C2 = -kx + ky;
00201     C3 = -kxky_ - kzSqr_;
00202     eqPop[5]  = t4 * (C1+C2+C3);
00203     eqPop[18] = t4 * (C1-C2+C3);
00204 
00205     // i=6 and i=19
00206     C2 = -kx - kz;
00207     C3 = kxkz_ - kySqr_;
00208     eqPop[6]  = t4 * (C1+C2+C3);
00209     eqPop[19] = t4 * (C1-C2+C3);
00210 
00211     // i=7 and i=20
00212     C2 = -kx + kz;
00213     C3 = -kxkz_ - kySqr_;
00214     eqPop[7]  = t4 * (C1+C2+C3);
00215     eqPop[20] = t4 * (C1-C2+C3);
00216 
00217     // i=8 and i=21
00218     C2 = -ky - kz;
00219     C3 = kykz_ - kxSqr_;
00220     eqPop[8]  = t4 * (C1+C2+C3);
00221     eqPop[21] = t4 * (C1-C2+C3);
00222 
00223     // i=9 and i=22
00224     C2 = -ky + kz;
00225     C3 = -kykz_ - kxSqr_;
00226     eqPop[9]  = t4 * (C1+C2+C3);
00227     eqPop[22] = t4 * (C1-C2+C3);
00228 
00229     // i=10 and i=23
00230     C2 = -kx -ky -kz;
00231     C3 = kxky_ + kxkz_ + kykz_;
00232     eqPop[10] = t10 * (C1+C2+C3);
00233     eqPop[23] = t10 * (C1-C2+C3);
00234 
00235     // i=11 and i=24
00236     C2 = -kx -ky +kz;
00237     C3 = kxky_ - kxkz_ - kykz_;
00238     eqPop[11] = t10 * (C1+C2+C3);
00239     eqPop[24] = t10 * (C1-C2+C3);
00240 
00241     // i=12 and i=25
00242     C2 = -kx +ky -kz;
00243     C3 = -kxky_ + kxkz_ - kykz_;
00244     eqPop[12] = t10 * (C1+C2+C3);
00245     eqPop[25] = t10 * (C1-C2+C3);
00246 
00247     // i=13 and i=26
00248     C2 = -kx +ky +kz;
00249     C3 = -kxky_ - kxkz_ + kykz_;
00250     eqPop[13] = t10 * (C1+C2+C3);
00251     eqPop[26] = t10 * (C1-C2+C3);
00252 }
00253 
00254 static T bgk_ma2_collision_base(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, bool incompressible) {
00255     T invRho = incompressible ? (T)1 : Descriptor::invRho(rhoBar);
00256     T one_m_omega = (T)1 - omega;
00257     T t0_omega = Descriptor::t[0] * omega;
00258     T t1_omega = Descriptor::t[1] * omega;
00259     T t4_omega = Descriptor::t[4] * omega;
00260     T t10_omega = Descriptor::t[10] * omega;
00261 
00262     T jSqr   = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00263     T kx     = (T)3 * j[0];
00264     T ky     = (T)3 * j[1];
00265     T kz     = (T)3 * j[2];
00266     T kxSqr_ = invRho / (T)2 * kx*kx;
00267     T kySqr_ = invRho / (T)2 * ky*ky;
00268     T kzSqr_ = invRho / (T)2 * kz*kz;
00269     T kxky_  = invRho * kx*ky;
00270     T kxkz_  = invRho * kx*kz;
00271     T kykz_  = invRho * ky*kz;
00272 
00273     T C1 = rhoBar + invRho*(T)3*jSqr;
00274     T C2, C3;
00275 
00276     // i=0
00277     C3 = -kxSqr_ - kySqr_ - kzSqr_;
00278     f[0] *= one_m_omega; f[0] += t0_omega * (C1+C3);
00279 
00280     // i=1 and i=14
00281     C2 = -kx;
00282     C3 = -kySqr_ - kzSqr_;
00283     f[1]  *= one_m_omega; f[1]  += t1_omega * (C1+C2+C3);
00284     f[14] *= one_m_omega; f[14] += t1_omega * (C1-C2+C3);
00285 
00286     // i=2 and i=15
00287     C2 = -ky;
00288     C3 = -kxSqr_ - kzSqr_;
00289     f[2]  *= one_m_omega; f[2]  += t1_omega * (C1+C2+C3);
00290     f[15] *= one_m_omega; f[15] += t1_omega * (C1-C2+C3);
00291 
00292     // i=3 and i=16
00293     C2 = -kz;
00294     C3 = -kxSqr_ - kySqr_;
00295     f[3]  *= one_m_omega; f[3]  += t1_omega * (C1+C2+C3);
00296     f[16] *= one_m_omega; f[16] += t1_omega * (C1-C2+C3);
00297 
00298     // i=4 and i=17
00299     C2 = -kx - ky;
00300     C3 = kxky_ - kzSqr_;
00301     f[4]  *= one_m_omega; f[4]  += t4_omega * (C1+C2+C3);
00302     f[17] *= one_m_omega; f[17] += t4_omega * (C1-C2+C3);
00303 
00304     // i=5 and i=18
00305     C2 = -kx + ky;
00306     C3 = -kxky_ - kzSqr_;
00307     f[5]  *= one_m_omega; f[5]  += t4_omega * (C1+C2+C3);
00308     f[18] *= one_m_omega; f[18] += t4_omega * (C1-C2+C3);
00309 
00310     // i=6 and i=19
00311     C2 = -kx - kz;
00312     C3 = kxkz_ - kySqr_;
00313     f[6]  *= one_m_omega; f[6]  += t4_omega * (C1+C2+C3);
00314     f[19] *= one_m_omega; f[19] += t4_omega * (C1-C2+C3);
00315 
00316     // i=7 and i=20
00317     C2 = -kx + kz;
00318     C3 = -kxkz_ - kySqr_;
00319     f[7]  *= one_m_omega; f[7]  += t4_omega * (C1+C2+C3);
00320     f[20] *= one_m_omega; f[20] += t4_omega * (C1-C2+C3);
00321 
00322     // i=8 and i=21
00323     C2 = -ky - kz;
00324     C3 = kykz_ - kxSqr_;
00325     f[8]  *= one_m_omega; f[8]  += t4_omega * (C1+C2+C3);
00326     f[21] *= one_m_omega; f[21] += t4_omega * (C1-C2+C3);
00327 
00328     // i=9 and i=22
00329     C2 = -ky + kz;
00330     C3 = -kykz_ - kxSqr_;
00331     f[9]  *= one_m_omega; f[9]  += t4_omega * (C1+C2+C3);
00332     f[22] *= one_m_omega; f[22] += t4_omega * (C1-C2+C3);
00333 
00334     // i=10 and i=23
00335     C2 = -kx -ky -kz;
00336     C3 = kxky_ + kxkz_ + kykz_;
00337     f[10] *= one_m_omega; f[10] += t10_omega * (C1+C2+C3);
00338     f[23] *= one_m_omega; f[23] += t10_omega * (C1-C2+C3);
00339 
00340     // i=11 and i=24
00341     C2 = -kx -ky +kz;
00342     C3 = kxky_ - kxkz_ - kykz_;
00343     f[11] *= one_m_omega; f[11] += t10_omega * (C1+C2+C3);
00344     f[24] *= one_m_omega; f[24] += t10_omega * (C1-C2+C3);
00345 
00346     // i=12 and i=25
00347     C2 = -kx +ky -kz;
00348     C3 = -kxky_ + kxkz_ - kykz_;
00349     f[12] *= one_m_omega; f[12] += t10_omega * (C1+C2+C3);
00350     f[25] *= one_m_omega; f[25] += t10_omega * (C1-C2+C3);
00351 
00352     // i=13 and i=26
00353     C2 = -kx +ky +kz;
00354     C3 = -kxky_ - kxkz_ + kykz_;
00355     f[13] *= one_m_omega; f[13] += t10_omega * (C1+C2+C3);
00356     f[26] *= one_m_omega; f[26] += t10_omega * (C1-C2+C3);
00357 
00358     return invRho*invRho*jSqr;
00359 }
00360 
00361 static T bgk_ma2_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega) {
00362     T invRho = Descriptor::invRho(rhoBar);
00363     const T jSqr = VectorTemplateImpl<T,Descriptor::d>::normSqr(j);
00364     for (plint iPop=0; iPop < Descriptor::q; ++iPop) {
00365         f[iPop] *= (T)1-omega;
00366         f[iPop] += omega * dynamicsTemplatesImpl<T,Descriptor>::bgk_ma2_equilibrium (
00367                                 iPop, rhoBar, invRho, j, jSqr );
00368     }
00369     return jSqr*invRho*invRho;
00370     //return bgk_ma2_collision_base(f, rhoBar, j, omega, false);
00371 }
00372 
00373 static T bgk_inc_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega) {
00374     return bgk_ma2_collision_base(f, rhoBar, j, omega, true);
00375 }
00376 
00377 static T rlb_collision(Array<T,Descriptor::q>& f, T rhoBar, T invRho, Array<T,3> const& j, Array<T,6> const& PiNeq, T omega ) {
00378     typedef dynamicsTemplatesImpl<T, descriptors::D3Q27DescriptorBase<T> > DH;
00379     const T jSqr = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00380 
00381     T piNeq0 = neqPiD3Q27<T>::fromPiToFneq0(PiNeq);
00382     T piNeq1 = neqPiD3Q27<T>::fromPiToFneq1(PiNeq);
00383     T piNeq2 = neqPiD3Q27<T>::fromPiToFneq2(PiNeq);
00384     T piNeq3 = neqPiD3Q27<T>::fromPiToFneq3(PiNeq);
00385     T piNeq4 = neqPiD3Q27<T>::fromPiToFneq4(PiNeq);
00386     T piNeq5 = neqPiD3Q27<T>::fromPiToFneq5(PiNeq);
00387     T piNeq6 = neqPiD3Q27<T>::fromPiToFneq6(PiNeq);
00388     T piNeq7 = neqPiD3Q27<T>::fromPiToFneq7(PiNeq);
00389     T piNeq8 = neqPiD3Q27<T>::fromPiToFneq8(PiNeq);
00390     T piNeq9 = neqPiD3Q27<T>::fromPiToFneq9(PiNeq);
00391     T piNeq10 = neqPiD3Q27<T>::fromPiToFneq10(PiNeq);
00392     T piNeq11 = neqPiD3Q27<T>::fromPiToFneq11(PiNeq);
00393     T piNeq12 = neqPiD3Q27<T>::fromPiToFneq12(PiNeq);
00394     T piNeq13 = neqPiD3Q27<T>::fromPiToFneq13(PiNeq);
00395 
00396     f[0]  = DH::bgk_ma2_equilibrium(0, rhoBar, invRho, j, jSqr)
00397                    + ((T)1-omega) * piNeq0;
00398     f[1]  = DH::bgk_ma2_equilibrium(1, rhoBar, invRho, j, jSqr)
00399                    + ((T)1-omega) * piNeq1;
00400     f[2]  = DH::bgk_ma2_equilibrium(2, rhoBar, invRho, j, jSqr)
00401                    + ((T)1-omega) * piNeq2;
00402     f[3]  = DH::bgk_ma2_equilibrium(3, rhoBar, invRho, j, jSqr)
00403                    + ((T)1-omega) * piNeq3;
00404     f[4]  = DH::bgk_ma2_equilibrium(4, rhoBar, invRho, j, jSqr)
00405                    + ((T)1-omega) * piNeq4;
00406     f[5]  = DH::bgk_ma2_equilibrium(5, rhoBar, invRho, j, jSqr)
00407                    + ((T)1-omega) * piNeq5;
00408     f[6]  = DH::bgk_ma2_equilibrium(6, rhoBar, invRho, j, jSqr)
00409                    + ((T)1-omega) * piNeq6;
00410     f[7]  = DH::bgk_ma2_equilibrium(7, rhoBar, invRho, j, jSqr)
00411                    + ((T)1-omega) * piNeq7;
00412     f[8]  = DH::bgk_ma2_equilibrium(8, rhoBar, invRho, j, jSqr)
00413                    + ((T)1-omega) * piNeq8;
00414     f[9]  = DH::bgk_ma2_equilibrium(9, rhoBar, invRho, j, jSqr)
00415                    + ((T)1-omega) * piNeq9;
00416     f[10]  = DH::bgk_ma2_equilibrium(10, rhoBar, invRho, j, jSqr)
00417                    + ((T)1-omega) * piNeq10;
00418     f[11]  = DH::bgk_ma2_equilibrium(11, rhoBar, invRho, j, jSqr)
00419                    + ((T)1-omega) * piNeq11;
00420     f[12]  = DH::bgk_ma2_equilibrium(12, rhoBar, invRho, j, jSqr)
00421                    + ((T)1-omega) * piNeq12;
00422     f[13]  = DH::bgk_ma2_equilibrium(13, rhoBar, invRho, j, jSqr)
00423                    + ((T)1-omega) * piNeq13;
00424     f[14]  = DH::bgk_ma2_equilibrium(14, rhoBar, invRho, j, jSqr)
00425                    + ((T)1-omega) * piNeq1;
00426     f[15]  = DH::bgk_ma2_equilibrium(15, rhoBar, invRho, j, jSqr)
00427                    + ((T)1-omega) * piNeq2;
00428     f[16]  = DH::bgk_ma2_equilibrium(16, rhoBar, invRho, j, jSqr)
00429                    + ((T)1-omega) * piNeq3;
00430     f[17]  = DH::bgk_ma2_equilibrium(17, rhoBar, invRho, j, jSqr)
00431                    + ((T)1-omega) * piNeq4;
00432     f[18]  = DH::bgk_ma2_equilibrium(18, rhoBar, invRho, j, jSqr)
00433                    + ((T)1-omega) * piNeq5;
00434     f[19]  = DH::bgk_ma2_equilibrium(19, rhoBar, invRho, j, jSqr)
00435                    + ((T)1-omega) * piNeq6;
00436     f[20]  = DH::bgk_ma2_equilibrium(20, rhoBar, invRho, j, jSqr)
00437                    + ((T)1-omega) * piNeq7;
00438     f[21]  = DH::bgk_ma2_equilibrium(21, rhoBar, invRho, j, jSqr)
00439                    + ((T)1-omega) * piNeq8;
00440     f[22]  = DH::bgk_ma2_equilibrium(22, rhoBar, invRho, j, jSqr)
00441                    + ((T)1-omega) * piNeq9;
00442     f[23]  = DH::bgk_ma2_equilibrium(23, rhoBar, invRho, j, jSqr)
00443                    + ((T)1-omega) * piNeq10;
00444     f[24]  = DH::bgk_ma2_equilibrium(24, rhoBar, invRho, j, jSqr)
00445                    + ((T)1-omega) * piNeq11;
00446     f[25]  = DH::bgk_ma2_equilibrium(25, rhoBar, invRho, j, jSqr)
00447                    + ((T)1-omega) * piNeq12;
00448     f[26]  = DH::bgk_ma2_equilibrium(26, rhoBar, invRho, j, jSqr)
00449                    + ((T)1-omega) * piNeq13;
00450 
00451     return jSqr*invRho*invRho;
00452 }
00453 
00454 static T bgk_ma2_constRho_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,Descriptor::d> const& j, T ratioRho, T omega) {
00455     T invRho = Descriptor::invRho(rhoBar);
00456     const T jSqr = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00457     for (plint iPop=0; iPop < Descriptor::q; ++iPop) {
00458         T feq = bgk_ma2_equilibrium(iPop, rhoBar, invRho, j, jSqr );
00459         f[iPop] =
00460           ratioRho*feq + Descriptor::t[iPop]*(ratioRho-(T)1) +
00461           ((T)1-omega)*(f[iPop]-feq);
00462     }
00463     return jSqr*invRho*invRho;
00464 }
00465 
00466 static T precond_bgk_ma2_equilibrium(plint iPop, T rhoBar, T invRho, Array<T,3> const& j, T jSqr, T invGamma ) {
00467     T c_j = Descriptor::c[iPop][0]*j[0] + Descriptor::c[iPop][1]*j[1] + Descriptor::c[iPop][2]*j[2];
00468     return Descriptor::t[iPop] * ( rhoBar + 3.*c_j + invGamma*invRho*(4.5*c_j*c_j - 1.5*jSqr) );
00469 }
00470 
00471 static T precond_bgk_ma2_collision_base (
00472         Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, T invGamma, bool incompressible )
00473 {
00474     T invRho = incompressible ? (T)1 : Descriptor::invRho(rhoBar);
00475     T one_m_omega = (T)1 - omega;
00476     T t0_omega = Descriptor::t[0] * omega;
00477     T t1_omega = Descriptor::t[1] * omega;
00478     T t4_omega = Descriptor::t[4] * omega;
00479     T t10_omega = Descriptor::t[10] * omega;
00480 
00481     T jSqr   = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00482     T kx     = (T)3 * j[0];
00483     T ky     = (T)3 * j[1];
00484     T kz     = (T)3 * j[2];
00485     T kxSqr_ = invGamma* invRho / (T)2 * kx*kx;
00486     T kySqr_ = invGamma* invRho / (T)2 * ky*ky;
00487     T kzSqr_ = invGamma* invRho / (T)2 * kz*kz;
00488     T kxky_  = invGamma* invRho * kx*ky;
00489     T kxkz_  = invGamma* invRho * kx*kz;
00490     T kykz_  = invGamma* invRho * ky*kz;
00491 
00492     T C1 = rhoBar + invGamma*invRho*(T)3*jSqr;
00493     T C2, C3;
00494 
00495     // i=0
00496     C3 = -kxSqr_ - kySqr_ - kzSqr_;
00497     f[0] *= one_m_omega; f[0] += t0_omega * (C1+C3);
00498 
00499     // i=1 and i=14
00500     C2 = -kx;
00501     C3 = -kySqr_ - kzSqr_;
00502     f[1]  *= one_m_omega; f[1]  += t1_omega * (C1+C2+C3);
00503     f[14] *= one_m_omega; f[14] += t1_omega * (C1-C2+C3);
00504 
00505     // i=2 and i=15
00506     C2 = -ky;
00507     C3 = -kxSqr_ - kzSqr_;
00508     f[2]  *= one_m_omega; f[2]  += t1_omega * (C1+C2+C3);
00509     f[15] *= one_m_omega; f[15] += t1_omega * (C1-C2+C3);
00510 
00511     // i=3 and i=16
00512     C2 = -kz;
00513     C3 = -kxSqr_ - kySqr_;
00514     f[3]  *= one_m_omega; f[3]  += t1_omega * (C1+C2+C3);
00515     f[16] *= one_m_omega; f[16] += t1_omega * (C1-C2+C3);
00516 
00517     // i=4 and i=17
00518     C2 = -kx - ky;
00519     C3 = kxky_ - kzSqr_;
00520     f[4]  *= one_m_omega; f[4]  += t4_omega * (C1+C2+C3);
00521     f[17] *= one_m_omega; f[17] += t4_omega * (C1-C2+C3);
00522 
00523     // i=5 and i=18
00524     C2 = -kx + ky;
00525     C3 = -kxky_ - kzSqr_;
00526     f[5]  *= one_m_omega; f[5]  += t4_omega * (C1+C2+C3);
00527     f[18] *= one_m_omega; f[18] += t4_omega * (C1-C2+C3);
00528 
00529     // i=6 and i=19
00530     C2 = -kx - kz;
00531     C3 = kxkz_ - kySqr_;
00532     f[6]  *= one_m_omega; f[6]  += t4_omega * (C1+C2+C3);
00533     f[19] *= one_m_omega; f[19] += t4_omega * (C1-C2+C3);
00534 
00535     // i=7 and i=20
00536     C2 = -kx + kz;
00537     C3 = -kxkz_ - kySqr_;
00538     f[7]  *= one_m_omega; f[7]  += t4_omega * (C1+C2+C3);
00539     f[20] *= one_m_omega; f[20] += t4_omega * (C1-C2+C3);
00540 
00541     // i=8 and i=21
00542     C2 = -ky - kz;
00543     C3 = kykz_ - kxSqr_;
00544     f[8]  *= one_m_omega; f[8]  += t4_omega * (C1+C2+C3);
00545     f[21] *= one_m_omega; f[21] += t4_omega * (C1-C2+C3);
00546 
00547     // i=9 and i=22
00548     C2 = -ky + kz;
00549     C3 = -kykz_ - kxSqr_;
00550     f[9]  *= one_m_omega; f[9]  += t4_omega * (C1+C2+C3);
00551     f[22] *= one_m_omega; f[22] += t4_omega * (C1-C2+C3);
00552 
00553     // i=10 and i=23
00554     C2 = -kx -ky -kz;
00555     C3 = kxky_ + kxkz_ + kykz_;
00556     f[10] *= one_m_omega; f[10] += t10_omega * (C1+C2+C3);
00557     f[23] *= one_m_omega; f[23] += t10_omega * (C1-C2+C3);
00558 
00559     // i=11 and i=24
00560     C2 = -kx -ky +kz;
00561     C3 = kxky_ - kxkz_ - kykz_;
00562     f[11] *= one_m_omega; f[11] += t10_omega * (C1+C2+C3);
00563     f[24] *= one_m_omega; f[24] += t10_omega * (C1-C2+C3);
00564 
00565     // i=12 and i=25
00566     C2 = -kx +ky -kz;
00567     C3 = -kxky_ + kxkz_ - kykz_;
00568     f[12] *= one_m_omega; f[12] += t10_omega * (C1+C2+C3);
00569     f[25] *= one_m_omega; f[25] += t10_omega * (C1-C2+C3);
00570 
00571     // i=13 and i=26
00572     C2 = -kx +ky +kz;
00573     C3 = -kxky_ - kxkz_ + kykz_;
00574     f[13] *= one_m_omega; f[13] += t10_omega * (C1+C2+C3);
00575     f[26] *= one_m_omega; f[26] += t10_omega * (C1-C2+C3);
00576 
00577     return invRho*invRho*jSqr;
00578 }
00579 
00580 static T precond_bgk_ma2_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, T invGamma) {
00581     T invRho = Descriptor::invRho(rhoBar);
00582     const T jSqr = VectorTemplateImpl<T,Descriptor::d>::normSqr(j);
00583     for (plint iPop=0; iPop < Descriptor::q; ++iPop) {
00584         f[iPop] *= (T)1-omega;
00585         f[iPop] += omega * dynamicsTemplatesImpl<T,Descriptor>::precond_bgk_ma2_equilibrium (
00586                                 iPop, rhoBar, invRho, j, jSqr, invGamma );
00587     }
00588     return jSqr*invRho*invRho;
00589     //return bgk_ma2_collision_base(f, rhoBar, j, omega, false);
00590 }
00591 
00592 };  //struct dynamicsTemplatesImpl<D3Q27DescriptorBase>
00593 
00594 
00595 template<typename T>
00596 struct neqPiD3Q19 {
00597 
00598     typedef SymmetricTensorImpl<T,3> S;
00599 
00600     static T fromPiToFneq0(Array<T,6> const& pi) {
00601         return (T)3/(T)2 * (
00602                  -(T)1/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00603                );
00604     }
00605 
00606     static T fromPiToFneq1(Array<T,6> const& pi) {
00607         return (T)1/(T)4 * (
00608                   (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00609                );
00610     }
00611 
00612     static T fromPiToFneq2(Array<T,6> const& pi) {
00613         return (T)1/(T)4 * (
00614                  -(T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00615                );
00616     }
00617 
00618     static T fromPiToFneq3(Array<T,6> const& pi) {
00619         return (T)1/(T)4 * (
00620                  -(T)1/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00621                );
00622     }
00623 
00624     static T fromPiToFneq4(Array<T,6> const& pi) {
00625         return (T)1/(T)8 * (
00626                   (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00627                   + (T)2*pi[S::xy]
00628                );
00629     }
00630 
00631     static T fromPiToFneq5(Array<T,6> const& pi) {
00632         return (T)1/(T)8 * (
00633                   (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
00634                   - (T)2*pi[S::xy]
00635                );
00636     }
00637 
00638     static T fromPiToFneq6(Array<T,6> const& pi) {
00639         return (T)1/(T)8 * (
00640                   (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00641                   + (T)2*pi[S::xz]
00642                );
00643     }
00644 
00645     static T fromPiToFneq7(Array<T,6> const& pi) {
00646         return (T)1/(T)8 * (
00647                   (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00648                   - (T)2*pi[S::xz]
00649                );
00650     }
00651 
00652     static T fromPiToFneq8(Array<T,6> const& pi) {
00653         return (T)1/(T)8 * (
00654                  -(T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00655                   + (T)2*pi[S::yz]
00656                );
00657     }
00658 
00659     static T fromPiToFneq9(Array<T,6> const& pi) {
00660         return (T)1/(T)8 * (
00661                  -(T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
00662                   - (T)2*pi[S::yz]
00663                );
00664     }
00665 
00666 };  // struct neqPiD3Q19
00667 
00668 
00669 
00670 // Efficient specialization for D3Q19 lattice
00671 template<typename T>
00672 struct dynamicsTemplatesImpl<T, descriptors::D3Q19DescriptorBase<T> > {
00673 
00674 typedef descriptors::D3Q19DescriptorBase<T> Descriptor;
00675 
00676 static T bgk_ma2_equilibrium(plint iPop, T rhoBar, T invRho, Array<T,3> const& j, T jSqr ) {
00677     T c_j = Descriptor::c[iPop][0]*j[0] + Descriptor::c[iPop][1]*j[1] + Descriptor::c[iPop][2]*j[2];
00678     return Descriptor::t[iPop] * ( rhoBar + 3.*c_j + invRho*(4.5*c_j*c_j - 1.5*jSqr) );
00679 }
00680 
00681 static void bgk_ma2_equilibria( T rhoBar, T invRho, Array<T,Descriptor::d> const& j,
00682                                 T jSqr, Array<T,Descriptor::q>& eqPop )
00683 {
00684     T t0 = Descriptor::t[0];
00685     T t1 = Descriptor::t[1];
00686     T t4 = Descriptor::t[4];
00687 
00688     T kx     = (T)3 * j[0];
00689     T ky     = (T)3 * j[1];
00690     T kz     = (T)3 * j[2];
00691     T kxSqr_ = invRho / (T)2 * kx*kx;
00692     T kySqr_ = invRho / (T)2 * ky*ky;
00693     T kzSqr_ = invRho / (T)2 * kz*kz;
00694     T kxky_  = invRho * kx*ky;
00695     T kxkz_  = invRho * kx*kz;
00696     T kykz_  = invRho * ky*kz;
00697 
00698     T C1 = rhoBar + invRho*(T)3*jSqr;
00699     T C2, C3;
00700 
00701     // i=0
00702     C3 = -kxSqr_ - kySqr_ - kzSqr_;
00703     eqPop[0] = t0 * (C1+C3);
00704 
00705     // i=1 and i=10
00706     C2 = -kx;
00707     C3 = -kySqr_ - kzSqr_;
00708     eqPop[1]  = t1 * (C1+C2+C3);
00709     eqPop[10] = t1 * (C1-C2+C3);
00710 
00711     // i=2 and i=11
00712     C2 = -ky;
00713     C3 = -kxSqr_ - kzSqr_;
00714     eqPop[2]  = t1 * (C1+C2+C3);
00715     eqPop[11] = t1 * (C1-C2+C3);
00716 
00717     // i=3 and i=12
00718     C2 = -kz;
00719     C3 = -kxSqr_ - kySqr_;
00720     eqPop[3]  = t1 * (C1+C2+C3);
00721     eqPop[12] = t1 * (C1-C2+C3);
00722 
00723     // i=4 and i=13
00724     C2 = -kx - ky;
00725     C3 = kxky_ - kzSqr_;
00726     eqPop[4]  = t4 * (C1+C2+C3);
00727     eqPop[13] = t4 * (C1-C2+C3);
00728 
00729     // i=5 and i=14
00730     C2 = -kx + ky;
00731     C3 = -kxky_ - kzSqr_;
00732     eqPop[5]  = t4 * (C1+C2+C3);
00733     eqPop[14] = t4 * (C1-C2+C3);
00734 
00735     // i=6 and i=15
00736     C2 = -kx - kz;
00737     C3 = kxkz_ - kySqr_;
00738     eqPop[6]  = t4 * (C1+C2+C3);
00739     eqPop[15] = t4 * (C1-C2+C3);
00740 
00741     // i=7 and i=16
00742     C2 = -kx + kz;
00743     C3 = -kxkz_ - kySqr_;
00744     eqPop[7]  = t4 * (C1+C2+C3);
00745     eqPop[16] = t4 * (C1-C2+C3);
00746 
00747     // i=8 and i=17
00748     C2 = -ky - kz;
00749     C3 = kykz_ - kxSqr_;
00750     eqPop[8]  = t4 * (C1+C2+C3);
00751     eqPop[17] = t4 * (C1-C2+C3);
00752 
00753     // i=9 and i=18
00754     C2 = -ky + kz;
00755     C3 = -kykz_ - kxSqr_;
00756     eqPop[9]  = t4 * (C1+C2+C3);
00757     eqPop[18] = t4 * (C1-C2+C3);
00758 }
00759 
00760 static T bgk_ma2_collision_base(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, bool incompressible) {
00761     T invRho = incompressible ? (T)1 : Descriptor::invRho(rhoBar);
00762     T one_m_omega = (T)1 - omega;
00763     T t0_omega = Descriptor::t[0] * omega;
00764     T t1_omega = Descriptor::t[1] * omega;
00765     T t4_omega = Descriptor::t[4] * omega;
00766 
00767     T jSqr   = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00768     T kx     = (T)3 * j[0];
00769     T ky     = (T)3 * j[1];
00770     T kz     = (T)3 * j[2];
00771     T kxSqr_ = invRho / (T)2 * kx*kx;
00772     T kySqr_ = invRho / (T)2 * ky*ky;
00773     T kzSqr_ = invRho / (T)2 * kz*kz;
00774     T kxky_  = invRho * kx*ky;
00775     T kxkz_  = invRho * kx*kz;
00776     T kykz_  = invRho * ky*kz;
00777 
00778     T C1 = rhoBar + invRho*(T)3*jSqr;
00779     T C2, C3;
00780 
00781     // i=0
00782     C3 = -kxSqr_ - kySqr_ - kzSqr_;
00783     f[0] *= one_m_omega; f[0] += t0_omega * (C1+C3);
00784 
00785     // i=1 and i=10
00786     C2 = -kx;
00787     C3 = -kySqr_ - kzSqr_;
00788     f[1]  *= one_m_omega; f[1]  += t1_omega * (C1+C2+C3);
00789     f[10] *= one_m_omega; f[10] += t1_omega * (C1-C2+C3);
00790 
00791     // i=2 and i=11
00792     C2 = -ky;
00793     C3 = -kxSqr_ - kzSqr_;
00794     f[2]  *= one_m_omega; f[2]  += t1_omega * (C1+C2+C3);
00795     f[11] *= one_m_omega; f[11] += t1_omega * (C1-C2+C3);
00796 
00797     // i=3 and i=12
00798     C2 = -kz;
00799     C3 = -kxSqr_ - kySqr_;
00800     f[3]  *= one_m_omega; f[3]  += t1_omega * (C1+C2+C3);
00801     f[12] *= one_m_omega; f[12] += t1_omega * (C1-C2+C3);
00802 
00803     // i=4 and i=13
00804     C2 = -kx - ky;
00805     C3 = kxky_ - kzSqr_;
00806     f[4]  *= one_m_omega; f[4]  += t4_omega * (C1+C2+C3);
00807     f[13] *= one_m_omega; f[13] += t4_omega * (C1-C2+C3);
00808 
00809     // i=5 and i=14
00810     C2 = -kx + ky;
00811     C3 = -kxky_ - kzSqr_;
00812     f[5]  *= one_m_omega; f[5]  += t4_omega * (C1+C2+C3);
00813     f[14] *= one_m_omega; f[14] += t4_omega * (C1-C2+C3);
00814 
00815     // i=6 and i=15
00816     C2 = -kx - kz;
00817     C3 = kxkz_ - kySqr_;
00818     f[6]  *= one_m_omega; f[6]  += t4_omega * (C1+C2+C3);
00819     f[15] *= one_m_omega; f[15] += t4_omega * (C1-C2+C3);
00820 
00821     // i=7 and i=16
00822     C2 = -kx + kz;
00823     C3 = -kxkz_ - kySqr_;
00824     f[7]  *= one_m_omega; f[7]  += t4_omega * (C1+C2+C3);
00825     f[16] *= one_m_omega; f[16] += t4_omega * (C1-C2+C3);
00826 
00827     // i=8 and i=17
00828     C2 = -ky - kz;
00829     C3 = kykz_ - kxSqr_;
00830     f[8]  *= one_m_omega; f[8]  += t4_omega * (C1+C2+C3);
00831     f[17] *= one_m_omega; f[17] += t4_omega * (C1-C2+C3);
00832 
00833     // i=9 and i=18
00834     C2 = -ky + kz;
00835     C3 = -kykz_ - kxSqr_;
00836     f[9]  *= one_m_omega; f[9]  += t4_omega * (C1+C2+C3);
00837     f[18] *= one_m_omega; f[18] += t4_omega * (C1-C2+C3);
00838 
00839     return invRho*invRho*jSqr;
00840 }
00841 
00842 static T bgk_ma2_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega) {
00843     return bgk_ma2_collision_base(f, rhoBar, j, omega, false);
00844 }
00845 
00846 static T bgk_inc_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega) {
00847     return bgk_ma2_collision_base(f, rhoBar, j, omega, true);
00848 }
00849 
00850 static T rlb_collision(Array<T,Descriptor::q>& f, T rhoBar, T invRho, Array<T,3> const& j, Array<T,6> const& PiNeq, T omega ) {
00851     typedef dynamicsTemplatesImpl<T, descriptors::D3Q19DescriptorBase<T> > DH;
00852     const T jSqr = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00853 
00854     T piNeq0 = neqPiD3Q19<T>::fromPiToFneq0(PiNeq);
00855     T piNeq1 = neqPiD3Q19<T>::fromPiToFneq1(PiNeq);
00856     T piNeq2 = neqPiD3Q19<T>::fromPiToFneq2(PiNeq);
00857     T piNeq3 = neqPiD3Q19<T>::fromPiToFneq3(PiNeq);
00858     T piNeq4 = neqPiD3Q19<T>::fromPiToFneq4(PiNeq);
00859     T piNeq5 = neqPiD3Q19<T>::fromPiToFneq5(PiNeq);
00860     T piNeq6 = neqPiD3Q19<T>::fromPiToFneq6(PiNeq);
00861     T piNeq7 = neqPiD3Q19<T>::fromPiToFneq7(PiNeq);
00862     T piNeq8 = neqPiD3Q19<T>::fromPiToFneq8(PiNeq);
00863     T piNeq9 = neqPiD3Q19<T>::fromPiToFneq9(PiNeq);
00864 
00865     f[0]  = DH::bgk_ma2_equilibrium(0, rhoBar, invRho, j, jSqr)
00866                    + ((T)1-omega) * piNeq0;
00867     f[1]  = DH::bgk_ma2_equilibrium(1, rhoBar, invRho, j, jSqr)
00868                    + ((T)1-omega) * piNeq1;
00869     f[2]  = DH::bgk_ma2_equilibrium(2, rhoBar, invRho, j, jSqr)
00870                    + ((T)1-omega) * piNeq2;
00871     f[3]  = DH::bgk_ma2_equilibrium(3, rhoBar, invRho, j, jSqr)
00872                    + ((T)1-omega) * piNeq3;
00873     f[4]  = DH::bgk_ma2_equilibrium(4, rhoBar, invRho, j, jSqr)
00874                    + ((T)1-omega) * piNeq4;
00875     f[5]  = DH::bgk_ma2_equilibrium(5, rhoBar, invRho, j, jSqr)
00876                    + ((T)1-omega) * piNeq5;
00877     f[6]  = DH::bgk_ma2_equilibrium(6, rhoBar, invRho, j, jSqr)
00878                    + ((T)1-omega) * piNeq6;
00879     f[7]  = DH::bgk_ma2_equilibrium(7, rhoBar, invRho, j, jSqr)
00880                    + ((T)1-omega) * piNeq7;
00881     f[8]  = DH::bgk_ma2_equilibrium(8, rhoBar, invRho, j, jSqr)
00882                    + ((T)1-omega) * piNeq8;
00883     f[9]  = DH::bgk_ma2_equilibrium(9, rhoBar, invRho, j, jSqr)
00884                    + ((T)1-omega) * piNeq9;
00885     f[10]  = DH::bgk_ma2_equilibrium(10, rhoBar, invRho, j, jSqr)
00886                    + ((T)1-omega) * piNeq1;
00887     f[11]  = DH::bgk_ma2_equilibrium(11, rhoBar, invRho, j, jSqr)
00888                    + ((T)1-omega) * piNeq2;
00889     f[12]  = DH::bgk_ma2_equilibrium(12, rhoBar, invRho, j, jSqr)
00890                    + ((T)1-omega) * piNeq3;
00891     f[13]  = DH::bgk_ma2_equilibrium(13, rhoBar, invRho, j, jSqr)
00892                    + ((T)1-omega) * piNeq4;
00893     f[14]  = DH::bgk_ma2_equilibrium(14, rhoBar, invRho, j, jSqr)
00894                    + ((T)1-omega) * piNeq5;
00895     f[15]  = DH::bgk_ma2_equilibrium(15, rhoBar, invRho, j, jSqr)
00896                    + ((T)1-omega) * piNeq6;
00897     f[16]  = DH::bgk_ma2_equilibrium(16, rhoBar, invRho, j, jSqr)
00898                    + ((T)1-omega) * piNeq7;
00899     f[17]  = DH::bgk_ma2_equilibrium(17, rhoBar, invRho, j, jSqr)
00900                    + ((T)1-omega) * piNeq8;
00901     f[18]  = DH::bgk_ma2_equilibrium(18, rhoBar, invRho, j, jSqr)
00902                    + ((T)1-omega) * piNeq9;
00903     return jSqr*invRho*invRho;
00904 }
00905 
00906 static T bgk_ma2_constRho_collision (
00907         Array<T,Descriptor::q>& f, T rhoBar, Array<T,Descriptor::d> const& j, T ratioRho, T omega )
00908 {
00909     T invRho = Descriptor::invRho(rhoBar);
00910     const T jSqr = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00911     for (plint iPop=0; iPop < Descriptor::q; ++iPop) {
00912         T feq = bgk_ma2_equilibrium(iPop, rhoBar, invRho, j, jSqr );
00913         f[iPop] =
00914           ratioRho*feq + Descriptor::t[iPop]*(ratioRho-(T)1) +
00915           ((T)1-omega)*(f[iPop]-feq);
00916     }
00917     return jSqr*invRho*invRho;
00918 }
00919 
00920 
00921 static T precond_bgk_ma2_equilibrium(plint iPop, T rhoBar, T invRho, Array<T,3> const& j, T jSqr, T invGamma ) {
00922     T c_j = Descriptor::c[iPop][0]*j[0] + Descriptor::c[iPop][1]*j[1] + Descriptor::c[iPop][2]*j[2];
00923     return Descriptor::t[iPop] * ( rhoBar + 3.*c_j + invGamma*invRho*(4.5*c_j*c_j - 1.5*jSqr) );
00924 }
00925 
00926 static T precond_bgk_ma2_collision_base( Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega,
00927                                          T invGamma, bool incompressible )
00928 {
00929     T invRho = incompressible ? (T)1 : Descriptor::invRho(rhoBar);
00930     T one_m_omega = (T)1 - omega;
00931     T t0_omega = Descriptor::t[0] * omega;
00932     T t1_omega = Descriptor::t[1] * omega;
00933     T t4_omega = Descriptor::t[4] * omega;
00934 
00935     T jSqr   = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
00936     T kx     = (T)3 * j[0];
00937     T ky     = (T)3 * j[1];
00938     T kz     = (T)3 * j[2];
00939     T kxSqr_ = invGamma* invRho / (T)2 * kx*kx;
00940     T kySqr_ = invGamma* invRho / (T)2 * ky*ky;
00941     T kzSqr_ = invGamma* invRho / (T)2 * kz*kz;
00942     T kxky_  = invGamma* invRho * kx*ky;
00943     T kxkz_  = invGamma* invRho * kx*kz;
00944     T kykz_  = invGamma* invRho * ky*kz;
00945 
00946     T C1 = rhoBar + invGamma*invRho*(T)3*jSqr;
00947     T C2, C3;
00948 
00949     // i=0
00950     C3 = -kxSqr_ - kySqr_ - kzSqr_;
00951     f[0] *= one_m_omega; f[0] += t0_omega * (C1+C3);
00952 
00953     // i=1 and i=10
00954     C2 = -kx;
00955     C3 = -kySqr_ - kzSqr_;
00956     f[1]  *= one_m_omega; f[1]  += t1_omega * (C1+C2+C3);
00957     f[10] *= one_m_omega; f[10] += t1_omega * (C1-C2+C3);
00958 
00959     // i=2 and i=11
00960     C2 = -ky;
00961     C3 = -kxSqr_ - kzSqr_;
00962     f[2]  *= one_m_omega; f[2]  += t1_omega * (C1+C2+C3);
00963     f[11] *= one_m_omega; f[11] += t1_omega * (C1-C2+C3);
00964 
00965     // i=3 and i=12
00966     C2 = -kz;
00967     C3 = -kxSqr_ - kySqr_;
00968     f[3]  *= one_m_omega; f[3]  += t1_omega * (C1+C2+C3);
00969     f[12] *= one_m_omega; f[12] += t1_omega * (C1-C2+C3);
00970 
00971     // i=4 and i=13
00972     C2 = -kx - ky;
00973     C3 = kxky_ - kzSqr_;
00974     f[4]  *= one_m_omega; f[4]  += t4_omega * (C1+C2+C3);
00975     f[13] *= one_m_omega; f[13] += t4_omega * (C1-C2+C3);
00976 
00977     // i=5 and i=14
00978     C2 = -kx + ky;
00979     C3 = -kxky_ - kzSqr_;
00980     f[5]  *= one_m_omega; f[5]  += t4_omega * (C1+C2+C3);
00981     f[14] *= one_m_omega; f[14] += t4_omega * (C1-C2+C3);
00982 
00983     // i=6 and i=15
00984     C2 = -kx - kz;
00985     C3 = kxkz_ - kySqr_;
00986     f[6]  *= one_m_omega; f[6]  += t4_omega * (C1+C2+C3);
00987     f[15] *= one_m_omega; f[15] += t4_omega * (C1-C2+C3);
00988 
00989     // i=7 and i=16
00990     C2 = -kx + kz;
00991     C3 = -kxkz_ - kySqr_;
00992     f[7]  *= one_m_omega; f[7]  += t4_omega * (C1+C2+C3);
00993     f[16] *= one_m_omega; f[16] += t4_omega * (C1-C2+C3);
00994 
00995     // i=8 and i=17
00996     C2 = -ky - kz;
00997     C3 = kykz_ - kxSqr_;
00998     f[8]  *= one_m_omega; f[8]  += t4_omega * (C1+C2+C3);
00999     f[17] *= one_m_omega; f[17] += t4_omega * (C1-C2+C3);
01000 
01001     // i=9 and i=18
01002     C2 = -ky + kz;
01003     C3 = -kykz_ - kxSqr_;
01004     f[9]  *= one_m_omega; f[9]  += t4_omega * (C1+C2+C3);
01005     f[18] *= one_m_omega; f[18] += t4_omega * (C1-C2+C3);
01006 
01007     return invRho*invRho*jSqr;
01008 }
01009 
01010 static T precond_bgk_ma2_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, T invGamma)
01011 {
01012     return precond_bgk_ma2_collision_base(f, rhoBar, j, omega, invGamma, false);
01013 }
01014 
01015 };  //struct dynamicsTemplatesImpl<D3Q19DescriptorBase>
01016 
01017 
01019 template<typename T>
01020 struct neqPiD3Q15 {
01021 
01022     typedef SymmetricTensorImpl<T,3> S;
01023 
01024     static T fromPiToFneq0(Array<T,6> const& pi) {
01025         return -(T)1/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz];
01026     }
01027 
01028     static T fromPiToFneq1(Array<T,6> const& pi) {
01029         return (T)1/(T)2 * (
01030                   (T)2/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
01031                );
01032     }
01033 
01034     static T fromPiToFneq2(Array<T,6> const& pi) {
01035         return (T)1/(T)2 * (
01036                  -(T)1/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] - (T)1/(T)3*pi[S::zz]
01037                );
01038     }
01039 
01040     static T fromPiToFneq3(Array<T,6> const& pi) {
01041         return (T)1/(T)2 * (
01042                  -(T)1/(T)3*pi[S::xx] - (T)1/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
01043                );
01044     }
01045 
01046     static T fromPiToFneq4(Array<T,6> const& pi) {
01047         return (T)1/(T)16 * (
01048                   (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
01049                   + pi[S::xy] + pi[S::xz] + pi[S::yz]
01050                );
01051     }
01052 
01053     static T fromPiToFneq5(Array<T,6> const& pi) {
01054         return (T)1/(T)16 * (
01055                   (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
01056                   + pi[S::xy] - pi[S::xz] - pi[S::yz]
01057                );
01058     }
01059 
01060     static T fromPiToFneq6(Array<T,6> const& pi) {
01061         return (T)1/(T)16 * (
01062                   (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
01063                   - pi[S::xy] + pi[S::xz] - pi[S::yz]
01064                );
01065     }
01066 
01067     static T fromPiToFneq7(Array<T,6> const& pi) {
01068         return (T)1/(T)16 * (
01069                   (T)2/(T)3*pi[S::xx] + (T)2/(T)3*pi[S::yy] + (T)2/(T)3*pi[S::zz]
01070                   - pi[S::xy] - pi[S::xz] + pi[S::yz]
01071                );
01072     }
01073 
01074 };  // struct neqPiD3Q15
01075 
01076 
01077 // Efficient specialization for D3Q15 lattice
01078 template<typename T>
01079 struct dynamicsTemplatesImpl<T, descriptors::D3Q15DescriptorBase<T> > {
01080 
01081 typedef descriptors::D3Q15DescriptorBase<T> Descriptor;
01082 
01083 static T bgk_ma2_equilibrium(plint iPop, T rhoBar, T invRho, Array<T,3> const& j, T jSqr ) {
01084     T c_j = Descriptor::c[iPop][0]*j[0] + Descriptor::c[iPop][1]*j[1] + Descriptor::c[iPop][2]*j[2];
01085     return Descriptor::t[iPop] * ( rhoBar + 3.*c_j + invRho*(4.5*c_j*c_j - 1.5*jSqr) );
01086 }
01087 
01088 static void bgk_ma2_equilibria( T rhoBar, T invRho, Array<T,Descriptor::d> const& j,
01089                                 T jSqr, Array<T,Descriptor::q>& eqPop )
01090 {
01091     T t0 = Descriptor::t[0];
01092     T t1 = Descriptor::t[1];
01093     T t4 = Descriptor::t[4];
01094 
01095     T kx     = (T)3 * j[0];
01096     T ky     = (T)3 * j[1];
01097     T kz     = (T)3 * j[2];
01098     T kxSqr_ = invRho / (T)2 * kx*kx;
01099     T kySqr_ = invRho / (T)2 * ky*ky;
01100     T kzSqr_ = invRho / (T)2 * kz*kz;
01101     T kxky_  = invRho * kx*ky;
01102     T kxkz_  = invRho * kx*kz;
01103     T kykz_  = invRho * ky*kz;
01104 
01105     T C1 = rhoBar + invRho*(T)3*jSqr;
01106     T C2, C3;
01107 
01108     // i=0
01109     C3 = -kxSqr_ - kySqr_ - kzSqr_;
01110     eqPop[0] = t0 * (C1+C3);
01111 
01112     // i=1 and i=8
01113     C2 = -kx;
01114     C3 = -kySqr_ - kzSqr_;
01115     eqPop[1]  = t1 * (C1+C2+C3);
01116     eqPop[8]  = t1 * (C1-C2+C3);
01117 
01118     // i=2 and i=9
01119     C2 = -ky;
01120     C3 = -kxSqr_ - kzSqr_;
01121     eqPop[2]  = t1 * (C1+C2+C3);
01122     eqPop[9]  = t1 * (C1-C2+C3);
01123 
01124     // i=3 and i=10
01125     C2 = -kz;
01126     C3 = -kxSqr_ - kySqr_;
01127     eqPop[3]  = t1 * (C1+C2+C3);
01128     eqPop[10] = t1 * (C1-C2+C3);
01129 
01130     // i=4 and i=11
01131     C2 = -kx -ky -kz;
01132     C3 = kxky_ + kxkz_ + kykz_;
01133     eqPop[4]  = t4 * (C1+C2+C3);
01134     eqPop[11] = t4 * (C1-C2+C3);
01135 
01136     // i=5 and i=12
01137     C2 = -kx -ky +kz;
01138     C3 = kxky_ - kxkz_ - kykz_;
01139     eqPop[5]  = t4 * (C1+C2+C3);
01140     eqPop[12] = t4 * (C1-C2+C3);
01141 
01142     // i=6 and i=13
01143     C2 = -kx +ky -kz;
01144     C3 = -kxky_ + kxkz_ - kykz_;
01145     eqPop[6]  = t4 * (C1+C2+C3);
01146     eqPop[13] = t4 * (C1-C2+C3);
01147 
01148     // i=7 and i=14
01149     C2 = -kx +ky +kz;
01150     C3 = -kxky_ - kxkz_ + kykz_;
01151     eqPop[7]  = t4 * (C1+C2+C3);
01152     eqPop[14] = t4 * (C1-C2+C3);
01153 }
01154 
01155 static T bgk_ma2_collision_base(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, bool incompressible) {
01156     T invRho = incompressible ? (T)1 : Descriptor::invRho(rhoBar);
01157     T one_m_omega = (T)1 - omega;
01158     T t0_omega = Descriptor::t[0] * omega;
01159     T t1_omega = Descriptor::t[1] * omega;
01160     T t4_omega = Descriptor::t[4] * omega;
01161 
01162     T jSqr   = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
01163     T kx     = (T)3 * j[0];
01164     T ky     = (T)3 * j[1];
01165     T kz     = (T)3 * j[2];
01166     T kxSqr_ = invRho / (T)2 * kx*kx;
01167     T kySqr_ = invRho / (T)2 * ky*ky;
01168     T kzSqr_ = invRho / (T)2 * kz*kz;
01169     T kxky_  = invRho * kx*ky;
01170     T kxkz_  = invRho * kx*kz;
01171     T kykz_  = invRho * ky*kz;
01172 
01173     T C1 = rhoBar + invRho*(T)3*jSqr;
01174     T C2, C3;
01175 
01176     // i=0
01177     C3 = -kxSqr_ - kySqr_ - kzSqr_;
01178     f[0] *= one_m_omega; f[0] += t0_omega * (C1+C3);
01179 
01180     // i=1 and i=8
01181     C2 = -kx;
01182     C3 = -kySqr_ - kzSqr_;
01183     f[1]  *= one_m_omega; f[1]  += t1_omega * (C1+C2+C3);
01184     f[8]  *= one_m_omega; f[8]  += t1_omega * (C1-C2+C3);
01185 
01186     // i=2 and i=9
01187     C2 = -ky;
01188     C3 = -kxSqr_ - kzSqr_;
01189     f[2]  *= one_m_omega; f[2]  += t1_omega * (C1+C2+C3);
01190     f[9]  *= one_m_omega; f[9]  += t1_omega * (C1-C2+C3);
01191 
01192     // i=3 and i=10
01193     C2 = -kz;
01194     C3 = -kxSqr_ - kySqr_;
01195     f[3]  *= one_m_omega; f[3]  += t1_omega * (C1+C2+C3);
01196     f[10] *= one_m_omega; f[10] += t1_omega * (C1-C2+C3);
01197 
01198     // i=4 and i=11
01199     C2 = -kx -ky -kz;
01200     C3 = kxky_ + kxkz_ + kykz_;
01201     f[4]  *= one_m_omega; f[4]  += t4_omega * (C1+C2+C3);
01202     f[11] *= one_m_omega; f[11] += t4_omega * (C1-C2+C3);
01203 
01204     // i=5 and i=12
01205     C2 = -kx -ky +kz;
01206     C3 = kxky_ - kxkz_ - kykz_;
01207     f[5]  *= one_m_omega; f[5]  += t4_omega * (C1+C2+C3);
01208     f[12] *= one_m_omega; f[12] += t4_omega * (C1-C2+C3);
01209 
01210     // i=6 and i=13
01211     C2 = -kx +ky -kz;
01212     C3 = -kxky_ + kxkz_ - kykz_;
01213     f[6]  *= one_m_omega; f[6]  += t4_omega * (C1+C2+C3);
01214     f[13] *= one_m_omega; f[13] += t4_omega * (C1-C2+C3);
01215 
01216     // i=7 and i=14
01217     C2 = -kx +ky +kz;
01218     C3 = -kxky_ - kxkz_ + kykz_;
01219     f[7]  *= one_m_omega; f[7]  += t4_omega * (C1+C2+C3);
01220     f[14] *= one_m_omega; f[14] += t4_omega * (C1-C2+C3);
01221 
01222     return invRho*invRho*jSqr;
01223 }
01224 
01225 
01226 
01227 static T bgk_ma2_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega) {
01228     return bgk_ma2_collision_base(f, rhoBar, j, omega, false);
01229 }
01230 
01231 static T bgk_inc_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega) {
01232     return bgk_ma2_collision_base(f, rhoBar, j, omega, true);
01233 }
01234 
01235 static T rlbCollision(Array<T,Descriptor::q>& f, T rhoBar, T invRho, Array<T,3> const& j, Array<T,6> const& PiNeq, T omega) {
01236     typedef dynamicsTemplatesImpl<T, descriptors::D3Q15DescriptorBase<T> > DH;
01237     const T jSqr = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
01238 
01239     T piNeq0 = neqPiD3Q15<T>::fromPiToFneq0(PiNeq);
01240     T piNeq1 = neqPiD3Q15<T>::fromPiToFneq1(PiNeq);
01241     T piNeq2 = neqPiD3Q15<T>::fromPiToFneq2(PiNeq);
01242     T piNeq3 = neqPiD3Q15<T>::fromPiToFneq3(PiNeq);
01243     T piNeq4 = neqPiD3Q15<T>::fromPiToFneq4(PiNeq);
01244     T piNeq5 = neqPiD3Q15<T>::fromPiToFneq5(PiNeq);
01245     T piNeq6 = neqPiD3Q15<T>::fromPiToFneq6(PiNeq);
01246     T piNeq7 = neqPiD3Q15<T>::fromPiToFneq7(PiNeq);
01247 
01248     f[0]  = DH::bgk_ma2_equilibrium(0, rhoBar, invRho, j, jSqr)
01249                    + ((T)1-omega) * piNeq0;
01250     f[1]  = DH::bgk_ma2_equilibrium(1, rhoBar, invRho, j, jSqr)
01251                    + ((T)1-omega) * piNeq1;
01252     f[2]  = DH::bgk_ma2_equilibrium(2, rhoBar, invRho, j, jSqr)
01253                    + ((T)1-omega) * piNeq2;
01254     f[3]  = DH::bgk_ma2_equilibrium(3, rhoBar, invRho, j, jSqr)
01255                    + ((T)1-omega) * piNeq3;
01256     f[4]  = DH::bgk_ma2_equilibrium(4, rhoBar, invRho, j, jSqr)
01257                    + ((T)1-omega) * piNeq4;
01258     f[5]  = DH::bgk_ma2_equilibrium(5, rhoBar, invRho, j, jSqr)
01259                    + ((T)1-omega) * piNeq5;
01260     f[6]  = DH::bgk_ma2_equilibrium(6, rhoBar, invRho, j, jSqr)
01261                    + ((T)1-omega) * piNeq6;
01262     f[7]  = DH::bgk_ma2_equilibrium(7, rhoBar, invRho, j, jSqr)
01263                    + ((T)1-omega) * piNeq7;
01264     f[8]  = DH::bgk_ma2_equilibrium(8, rhoBar, invRho, j, jSqr)
01265                    + ((T)1-omega) * piNeq1;
01266     f[9]  = DH::bgk_ma2_equilibrium(9, rhoBar, invRho, j, jSqr)
01267                    + ((T)1-omega) * piNeq2;
01268     f[10]  = DH::bgk_ma2_equilibrium(10,rhoBar, invRho, j, jSqr)
01269                    + ((T)1-omega) * piNeq3;
01270     f[11]  = DH::bgk_ma2_equilibrium(11,rhoBar, invRho, j, jSqr)
01271                    + ((T)1-omega) * piNeq4;
01272     f[12]  = DH::bgk_ma2_equilibrium(12,rhoBar, invRho, j, jSqr)
01273                    + ((T)1-omega) * piNeq5;
01274     f[13]  = DH::bgk_ma2_equilibrium(13,rhoBar, invRho, j, jSqr)
01275                    + ((T)1-omega) * piNeq6;
01276     f[14]  = DH::bgk_ma2_equilibrium(14,rhoBar, invRho, j, jSqr)
01277                    + ((T)1-omega) * piNeq7;
01278     return jSqr*invRho*invRho;
01279 }
01280 
01281 static T bgk_ma2_constRho_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,Descriptor::d> const& j, T ratioRho, T omega) {
01282     T invRho = Descriptor::invRho(rhoBar);
01283     const T jSqr = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
01284     for (plint iPop=0; iPop < Descriptor::q; ++iPop) {
01285         T feq = bgk_ma2_equilibrium(iPop, rhoBar, invRho, j, jSqr );
01286         f[iPop] =
01287           ratioRho*feq + Descriptor::t[iPop]*(ratioRho-(T)1) +
01288           ((T)1-omega)*(f[iPop]-feq);
01289     }
01290     return jSqr*invRho*invRho;
01291 }
01292 
01293 
01294 static T precond_bgk_ma2_equilibrium(plint iPop, T rhoBar, T invRho, Array<T,3> const& j, T jSqr, T invGamma )
01295 {
01296     T c_j = Descriptor::c[iPop][0]*j[0] + Descriptor::c[iPop][1]*j[1] + Descriptor::c[iPop][2]*j[2];
01297     return Descriptor::t[iPop] * ( rhoBar + 3.*c_j + invGamma*invRho*(4.5*c_j*c_j - 1.5*jSqr) );
01298 }
01299 
01300 static T precond_bgk_ma2_collision_base (
01301         Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, T invGamma, bool incompressible )
01302 {
01303     T invRho = incompressible ? (T)1 : Descriptor::invRho(rhoBar);
01304     T one_m_omega = (T)1 - omega;
01305     T t0_omega = Descriptor::t[0] * omega;
01306     T t1_omega = Descriptor::t[1] * omega;
01307     T t4_omega = Descriptor::t[4] * omega;
01308 
01309     T jSqr   = j[0]*j[0] + j[1]*j[1] + j[2]*j[2];
01310     T kx     = (T)3 * j[0];
01311     T ky     = (T)3 * j[1];
01312     T kz     = (T)3 * j[2];
01313     T kxSqr_ = invGamma* invRho / (T)2 * kx*kx;
01314     T kySqr_ = invGamma* invRho / (T)2 * ky*ky;
01315     T kzSqr_ = invGamma* invRho / (T)2 * kz*kz;
01316     T kxky_  = invGamma* invRho * kx*ky;
01317     T kxkz_  = invGamma* invRho * kx*kz;
01318     T kykz_  = invGamma* invRho * ky*kz;
01319 
01320     T C1 = rhoBar + invGamma*invRho*(T)3*jSqr;
01321     T C2, C3;
01322 
01323     // i=0
01324     C3 = -kxSqr_ - kySqr_ - kzSqr_;
01325     f[0] *= one_m_omega; f[0] += t0_omega * (C1+C3);
01326 
01327     // i=1 and i=8
01328     C2 = -kx;
01329     C3 = -kySqr_ - kzSqr_;
01330     f[1]  *= one_m_omega; f[1]  += t1_omega * (C1+C2+C3);
01331     f[8]  *= one_m_omega; f[8]  += t1_omega * (C1-C2+C3);
01332 
01333     // i=2 and i=9
01334     C2 = -ky;
01335     C3 = -kxSqr_ - kzSqr_;
01336     f[2]  *= one_m_omega; f[2]  += t1_omega * (C1+C2+C3);
01337     f[9]  *= one_m_omega; f[9]  += t1_omega * (C1-C2+C3);
01338 
01339     // i=3 and i=10
01340     C2 = -kz;
01341     C3 = -kxSqr_ - kySqr_;
01342     f[3]  *= one_m_omega; f[3]  += t1_omega * (C1+C2+C3);
01343     f[10] *= one_m_omega; f[10] += t1_omega * (C1-C2+C3);
01344 
01345     // i=4 and i=11
01346     C2 = -kx -ky -kz;
01347     C3 = kxky_ + kxkz_ + kykz_;
01348     f[4]  *= one_m_omega; f[4]  += t4_omega * (C1+C2+C3);
01349     f[11] *= one_m_omega; f[11] += t4_omega * (C1-C2+C3);
01350 
01351     // i=5 and i=12
01352     C2 = -kx -ky +kz;
01353     C3 = kxky_ - kxkz_ - kykz_;
01354     f[5]  *= one_m_omega; f[5]  += t4_omega * (C1+C2+C3);
01355     f[12] *= one_m_omega; f[12] += t4_omega * (C1-C2+C3);
01356 
01357     // i=6 and i=13
01358     C2 = -kx +ky -kz;
01359     C3 = -kxky_ + kxkz_ - kykz_;
01360     f[6]  *= one_m_omega; f[6]  += t4_omega * (C1+C2+C3);
01361     f[13] *= one_m_omega; f[13] += t4_omega * (C1-C2+C3);
01362 
01363     // i=7 and i=14
01364     C2 = -kx +ky +kz;
01365     C3 = -kxky_ - kxkz_ + kykz_;
01366     f[7]  *= one_m_omega; f[7]  += t4_omega * (C1+C2+C3);
01367     f[14] *= one_m_omega; f[14] += t4_omega * (C1-C2+C3);
01368 
01369     return invRho*invRho*jSqr;
01370 }
01371 
01372 static T precond_bgk_ma2_collision(Array<T,Descriptor::q>& f, T rhoBar, Array<T,3> const& j, T omega, T invGamma)
01373 {
01374     return bgk_ma2_collision_base(f, rhoBar, j, omega, invGamma, false);
01375 }
01376 
01377 
01378 };  //struct dynamicsTemplatesImpl<D3Q15DescriptorBase>
01379 
01380 }  // namespace plb
01381 
01382 #endif  // DYNAMICS_TEMPLATES_3D_H