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

finiteDifferenceBoundaryProcessor3D.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 #ifndef FINITE_DIFFERENCE_BOUNDARY_PROCESSOR_3D_HH
00026 #define FINITE_DIFFERENCE_BOUNDARY_PROCESSOR_3D_HH
00027 
00028 #include "boundaryCondition/finiteDifferenceBoundaryProcessor3D.h"
00029 #include "finiteDifference/finiteDifference3D.h"
00030 #include "atomicBlock/blockLattice3D.h"
00031 #include "latticeBoltzmann/offEquilibriumTemplates.h"
00032 #include "latticeBoltzmann/geometricOperationTemplates.h"
00033 #include "core/processorIdentifiers3D.h"
00034 #include <typeinfo>
00035 
00036 namespace plb {
00037 
00038 namespace fdBoundaryAlgorithm {
00039 
00040 
00041 
00042 }  // namespace fdBoundaryAlgorithm
00043 
00045 
00046 template<typename T, template<typename U> class Descriptor, int direction, int orientation>
00047 const int PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>::staticId =
00048     meta::registerProcessor3D < PlaneFdBoundaryFunctional3D<T, Descriptor, direction, orientation>,
00049                                 T, Descriptor, direction, orientation> (std::string("PlaneFdBoundary3D"));
00050 
00051 template<typename T, template<typename U> class Descriptor, int direction, int orientation>
00052 void PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>::process (
00053         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00054 {
00055     PLB_ASSERT( domain.x0==domain.x1 || domain.y0==domain.y1 ||
00056                 domain.z0==domain.z1 );
00057 
00058     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00059         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00060             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00061                 processCell(iX,iY,iZ, lattice);
00062             }
00063         }
00064     }
00065 }
00066 
00067 template<typename T, template<typename U> class Descriptor, int direction, int orientation>
00068 void PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>::processCell (
00069         plint iX, plint iY, plint iZ, BlockLattice3D<T,Descriptor>& lattice )
00070 {
00071     typedef SymmetricTensorImpl<T,Descriptor<T>::d> S;
00072     Array<T,Descriptor<T>::d> dx_u, dy_u, dz_u;
00073     Cell<T,Descriptor>& cell = lattice.get(iX,iY,iZ);
00074     Dynamics<T,Descriptor>& dynamics = cell.getDynamics();
00075     T rho = cell.computeDensity();
00076     Array<T,Descriptor<T>:: d> vel;
00077     cell.computeVelocity(vel);
00078 
00079     interpolateGradients<0> ( lattice, dx_u, iX, iY, iZ );
00080     interpolateGradients<1> ( lattice, dy_u, iX, iY, iZ );
00081     interpolateGradients<2> ( lattice, dz_u, iX, iY, iZ );
00082     T dx_ux = dx_u[0];
00083     T dy_ux = dy_u[0];
00084     T dz_ux = dz_u[0];
00085     T dx_uy = dx_u[1];
00086     T dy_uy = dy_u[1];
00087     T dz_uy = dz_u[1];
00088     T dx_uz = dx_u[2];
00089     T dy_uz = dy_u[2];
00090     T dz_uz = dz_u[2];
00091     T omega = cell.getDynamics().getOmega();
00092     T sToPi = - rho / Descriptor<T>::invCs2 / omega;
00093     Array<T,SymmetricTensor<T,Descriptor>::n> pi;
00094     pi[S::xx] = (T)2 * dx_ux * sToPi;
00095     pi[S::yy] = (T)2 * dy_uy * sToPi;
00096     pi[S::zz] = (T)2 * dz_uz * sToPi;
00097     pi[S::xy] = (dx_uy + dy_ux) * sToPi;
00098     pi[S::xz] = (dx_uz + dz_ux) * sToPi;
00099     pi[S::yz] = (dy_uz + dz_uy) * sToPi;
00100 
00101     Array<T,Descriptor<T>::d> j;
00102     if (cell.getDynamics().velIsJ()) {
00103         j = vel;
00104     }
00105     else {
00106         j = rho*vel;
00107     }
00108     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00109 
00110     // Computation of the particle distribution functions
00111     // according to the regularized formula
00112     for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop)
00113         cell[iPop] = dynamics.computeEquilibrium(iPop,Descriptor<T>::rhoBar(rho),j,jSqr) +
00114                          offEquilibriumTemplates<T,Descriptor>::fromPiToFneq(iPop, pi);
00115 }
00116 
00117 template<typename T, template<typename U> class Descriptor, int direction, int orientation>
00118 PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>*
00119      PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>::clone() const
00120 {
00121     return new PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>(*this);
00122 }
00123 
00124 template<typename T, template<typename U> class Descriptor, int direction, int orientation>
00125 template<int deriveDirection>
00126 void PlaneFdBoundaryFunctional3D<T,Descriptor,direction,orientation>::
00127     interpolateGradients(BlockLattice3D<T,Descriptor> const& lattice, Array<T,Descriptor<T>::d>& velDeriv,
00128                          plint iX, plint iY, plint iZ)
00129 {
00130     fd::DirectedGradients3D<T, Descriptor, direction, orientation, deriveDirection, direction==deriveDirection>::
00131         o1_velocityDerivative(velDeriv, lattice, iX, iY, iZ);
00132 }
00133 
00134 
00136 
00137 
00138 template<typename T, template<typename U> class Descriptor, int plane, int normal1, int normal2>
00139 const int OuterVelocityEdgeFunctional3D<T,Descriptor,plane,normal1,normal2>::staticId =
00140     meta::registerProcessor3D < OuterVelocityEdgeFunctional3D<T, Descriptor, plane,normal1,normal2>,
00141                                 T, Descriptor, plane,normal1,normal2> (std::string("OuterVelocityEdge"));
00142 
00143 template<typename T, template<typename U> class Descriptor, int plane, int normal1, int normal2>
00144 void OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>::process (
00145         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00146 {
00147     PLB_ASSERT (
00148             (plane==2 && domain.x0==domain.x1 && domain.y0==domain.y1) ||
00149             (plane==1 && domain.x0==domain.x1 && domain.z0==domain.z1) ||
00150             (plane==0 && domain.y0==domain.y1 && domain.z0==domain.z1)     );
00151 
00152     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00153         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00154             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00155                 processCell(iX,iY,iZ, lattice);
00156             }
00157         }
00158     }
00159 }
00160 
00161 template<typename T, template<typename U> class Descriptor, int plane, int normal1, int normal2>
00162 void OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>::processCell (
00163         plint iX, plint iY, plint iZ, BlockLattice3D<T,Descriptor>& lattice )
00164 {
00165     typedef SymmetricTensorImpl<T,Descriptor<T>::d> S;
00166     Cell<T,Descriptor>& cell = lattice.get(iX,iY,iZ);
00167     Dynamics<T,Descriptor>& dynamics = cell.getDynamics();
00168 
00169     T rho10 = getNeighborRho(iX,iY,iZ,1,0, lattice);
00170     T rho01 = getNeighborRho(iX,iY,iZ,0,1, lattice);
00171     T rho20 = getNeighborRho(iX,iY,iZ,2,0, lattice);
00172     T rho02 = getNeighborRho(iX,iY,iZ,0,2, lattice);
00173     T rho = (T)2/(T)3*(rho01+rho10)-(T)1/(T)6*(rho02+rho20);
00174 
00175     std::vector<Array<T,3> > dA_uB_(3);
00176     interpolateGradients<plane,0>            ( lattice, dA_uB_[0], iX, iY, iZ );
00177     interpolateGradients<direction1,normal1> ( lattice, dA_uB_[1], iX, iY, iZ );
00178     interpolateGradients<direction2,normal2> ( lattice, dA_uB_[2], iX, iY, iZ );
00179     std::vector<Array<T,3> > dA_uB(3);
00180     for (int iBeta=0; iBeta<3; ++iBeta) {
00181         dA_uB[plane][iBeta]      = dA_uB_[0][iBeta];
00182         dA_uB[direction1][iBeta] = dA_uB_[1][iBeta];
00183         dA_uB[direction2][iBeta] = dA_uB_[2][iBeta];
00184     }
00185     T omega = dynamics.getOmega();
00186     T sToPi = - rho / Descriptor<T>::invCs2 / omega;
00187     Array<T,SymmetricTensor<T,Descriptor>::n> pi;
00188     pi[S::xx] = (T)2 * dA_uB[0][0] * sToPi;
00189     pi[S::yy] = (T)2 * dA_uB[1][1] * sToPi;
00190     pi[S::zz] = (T)2 * dA_uB[2][2] * sToPi;
00191     pi[S::xy] = (dA_uB[0][1]+dA_uB[1][0]) * sToPi;
00192     pi[S::xz] = (dA_uB[0][2]+dA_uB[2][0]) * sToPi;
00193     pi[S::yz] = (dA_uB[1][2]+dA_uB[2][1]) * sToPi;
00194 
00195     // Computation of the particle distribution functions
00196     // according to the regularized formula
00197     Array<T,Descriptor<T>::d> vel, j;
00198     cell.computeVelocity(vel);
00199 
00200     if (cell.getDynamics().velIsJ()) {
00201         j = vel;
00202     }
00203     else {
00204         j = rho*vel;
00205     }
00206     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00207 
00208     for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop) {
00209         cell[iPop] = dynamics.computeEquilibrium(iPop,Descriptor<T>::rhoBar(rho),j,jSqr) +
00210                          offEquilibriumTemplates<T,Descriptor>::fromPiToFneq(iPop, pi);
00211     }
00212 }
00213 
00214 template<typename T, template<typename U> class Descriptor, int plane, int normal1, int normal2>
00215 OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>*
00216     OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>::clone() const
00217 {
00218     return new OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>(*this);
00219 }
00220 
00221 template<typename T, template<typename U> class Descriptor, int plane, int normal1, int normal2>
00222 T OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>::
00223     getNeighborRho(plint x, plint y, plint z, plint step1, plint step2, BlockLattice3D<T,Descriptor> const& lattice)
00224 {
00225     Array<int,3> coords (x, y, z);
00226     coords[direction1] += -normal1*step1;
00227     coords[direction2] += -normal2*step2;
00228     return lattice.get(coords[0], coords[1], coords[2]).computeDensity();
00229 }
00230 
00231 template<typename T, template<typename U> class Descriptor, int plane, int normal1, int normal2>
00232 template<int deriveDirection, int orientation>
00233 void OuterVelocityEdgeFunctional3D<T,Descriptor, plane,normal1,normal2>::
00234     interpolateGradients(BlockLattice3D<T,Descriptor> const& lattice,
00235                          Array<T,Descriptor<T>::d>& velDeriv,
00236                          plint iX, plint iY, plint iZ)
00237 {
00238     fd::DirectedGradients3D<T,Descriptor,deriveDirection,orientation,deriveDirection,deriveDirection!=plane>::
00239         o1_velocityDerivative(velDeriv, lattice, iX, iY, iZ);
00240 }
00241 
00243 
00244 template<typename T, template<typename U> class Descriptor, int xNormal, int yNormal, int zNormal>
00245 const int OuterVelocityCornerFunctional3D<T,Descriptor,xNormal,yNormal,zNormal>::staticId =
00246     meta::registerProcessor3D < OuterVelocityCornerFunctional3D<T, Descriptor, xNormal,yNormal,zNormal>,
00247                                 T, Descriptor, xNormal,yNormal,zNormal> (std::string("OuterVelocityCorner3D"));
00248 
00249 template<typename T, template<typename U> class Descriptor, int xNormal, int yNormal, int zNormal>
00250 void OuterVelocityCornerFunctional3D<T, Descriptor, xNormal, yNormal, zNormal>::process (
00251         Box3D domain, BlockLattice3D<T,Descriptor>& lattice )
00252 {
00253     plint x = domain.x0;
00254     plint y = domain.y0;
00255     plint z = domain.z0;
00256     PLB_ASSERT( x==domain.x1 && y==domain.y1 && z==domain.z1 );
00257 
00258     processCell(x,y,z, lattice);
00259 }
00260 
00261 template<typename T, template<typename U> class Descriptor, int xNormal, int yNormal, int zNormal>
00262 void OuterVelocityCornerFunctional3D<T, Descriptor, xNormal, yNormal, zNormal>::processCell (
00263         plint iX, plint iY, plint iZ, BlockLattice3D<T,Descriptor>& lattice )
00264 {
00265     typedef SymmetricTensorImpl<T,Descriptor<T>::d> S;
00266     Cell<T,Descriptor>& cell = lattice.get(iX,iY,iZ);
00267     Dynamics<T,Descriptor>& dynamics = cell.getDynamics();
00268 
00269     T rho100 = lattice.get(iX - 1*xNormal, iY - 0*yNormal, iZ - 0*zNormal).computeDensity();
00270     T rho010 = lattice.get(iX - 0*xNormal, iY - 1*yNormal, iZ - 0*zNormal).computeDensity();
00271     T rho001 = lattice.get(iX - 0*xNormal, iY - 0*yNormal, iZ - 1*zNormal).computeDensity();
00272     T rho = (T)1/(T)3 * (rho001 + rho010 + rho100);
00273 
00274     Array<T,Descriptor<T>::d> dx_u, dy_u, dz_u;
00275     fd::DirectedGradients3D<T, Descriptor, 0, xNormal, 0, true>::o1_velocityDerivative(dx_u, lattice, iX,iY,iZ);
00276     fd::DirectedGradients3D<T, Descriptor, 1, yNormal, 0, true>::o1_velocityDerivative(dy_u, lattice, iX,iY,iZ);
00277     fd::DirectedGradients3D<T, Descriptor, 2, zNormal, 0, true>::o1_velocityDerivative(dz_u, lattice, iX,iY,iZ);
00278 
00279     T dx_ux = dx_u[0];
00280     T dy_ux = dy_u[0];
00281     T dz_ux = dz_u[0];
00282     T dx_uy = dx_u[1];
00283     T dy_uy = dy_u[1];
00284     T dz_uy = dz_u[1];
00285     T dx_uz = dx_u[2];
00286     T dy_uz = dy_u[2];
00287     T dz_uz = dz_u[2];
00288     T omega = dynamics.getOmega();
00289     T sToPi = - rho / Descriptor<T>::invCs2 / omega;
00290     Array<T,SymmetricTensor<T,Descriptor>::n> pi;
00291     pi[S::xx] = (T)2 * dx_ux * sToPi;
00292     pi[S::yy] = (T)2 * dy_uy * sToPi;
00293     pi[S::zz] = (T)2 * dz_uz * sToPi;
00294     pi[S::xy] = (dx_uy + dy_ux) * sToPi;
00295     pi[S::xz] = (dx_uz + dz_ux) * sToPi;
00296     pi[S::yz] = (dy_uz + dz_uy) * sToPi;
00297 
00298     // Computation of the particle distribution functions
00299     // according to the regularized formula
00300     Array<T,Descriptor<T>::d> vel, j;
00301     cell.computeVelocity(vel);
00302     if (cell.getDynamics().velIsJ()) {
00303         j = vel;
00304     }
00305     else {
00306         j = rho*vel;
00307     }
00308     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00309 
00310     for (plint iPop = 0; iPop < Descriptor<T>::q; ++iPop) {
00311         cell[iPop] = dynamics.computeEquilibrium(iPop,Descriptor<T>::rhoBar(rho),j,jSqr) +
00312                          offEquilibriumTemplates<T,Descriptor>::fromPiToFneq(iPop, pi);
00313     }
00314 }
00315 
00316 template<typename T, template<typename U> class Descriptor, int xNormal, int yNormal, int zNormal>
00317 OuterVelocityCornerFunctional3D<T, Descriptor, xNormal, yNormal, zNormal>*
00318      OuterVelocityCornerFunctional3D<T, Descriptor, xNormal, yNormal, zNormal>::clone() const
00319 {
00320     return new OuterVelocityCornerFunctional3D<T, Descriptor, xNormal, yNormal, zNormal>(*this);
00321 }
00322 
00323 }  // namespace plb
00324 
00325 #endif  // FINITE_DIFFERENCE_BOUNDARY_PROCESSOR_3D_HH