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

guoAdvDiffOffLatticeModel3D.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 GUO_ADV_DIFF_OFF_LATTICE_MODEL_3D_HH
00026 #define GUO_ADV_DIFF_OFF_LATTICE_MODEL_3D_HH
00027 
00028 #include "offLattice/guoAdvDiffOffLatticeModel3D.h"
00029 #include "offLattice/nextNeighbors3D.h"
00030 #include "latticeBoltzmann/geometricOperationTemplates.h"
00031 #include "latticeBoltzmann/externalFieldAccess.h"
00032 #include <algorithm>
00033 #include <cmath>
00034 
00035 namespace plb {
00036 
00037 template<typename T, template<typename U> class Descriptor>
00038 GuoAdvDiffOffLatticeModel3D<T,Descriptor>::GuoAdvDiffOffLatticeModel3D (
00039         BoundaryShape3D<T,Array<T,2> >* shape_, int flowType_ )
00040     : OffLatticeModel3D<T,Array<T,2> >(shape_, flowType_)
00041 { }
00042 
00043 template<typename T, template<typename U> class Descriptor>
00044 GuoAdvDiffOffLatticeModel3D<T,Descriptor>::GuoAdvDiffOffLatticeModel3D (
00045         GuoAdvDiffOffLatticeModel3D<T,Descriptor> const& rhs )
00046     : OffLatticeModel3D<T,Array<T,2> >(rhs)
00047 { }
00048 
00049 template<typename T, template<typename U> class Descriptor>
00050 GuoAdvDiffOffLatticeModel3D<T,Descriptor>&
00051     GuoAdvDiffOffLatticeModel3D<T,Descriptor>::operator=(GuoAdvDiffOffLatticeModel3D<T,Descriptor> const& rhs)
00052 {
00053     OffLatticeModel3D<T,Array<T,2> >::operator=(rhs);
00054     return *this;
00055 }
00056 
00057 template<typename T, template<typename U> class Descriptor>
00058 GuoAdvDiffOffLatticeModel3D<T,Descriptor>* GuoAdvDiffOffLatticeModel3D<T,Descriptor>::clone() const {
00059     return new GuoAdvDiffOffLatticeModel3D(*this);
00060 }
00061 
00062 template<typename T, template<typename U> class Descriptor>
00063 plint GuoAdvDiffOffLatticeModel3D<T,Descriptor>::getNumNeighbors() const {
00064     return 2;
00065 }
00066 
00067 template<typename T, template<typename U> class Descriptor>
00068 void GuoAdvDiffOffLatticeModel3D<T,Descriptor>::prepareCell (
00069         Dot3D const& cellLocation,
00070         AtomicContainerBlock3D& container )
00071 {
00072     Dot3D offset = container.getLocation();
00073     GuoAdvDiffOffLatticeInfo3D* info =
00074         dynamic_cast<GuoAdvDiffOffLatticeInfo3D*>(container.getData());
00075     PLB_ASSERT( info );
00076     if (!this->isFluid(cellLocation+offset)) {
00077         std::vector<std::pair<int,int> > liquidNeighbors;
00078         std::vector<plint> ids;
00079         for (int iNeighbor=0; iNeighbor<NextNeighbor<T>::numNeighbors; ++iNeighbor) {
00080             int const* c = NextNeighbor<T>::c[iNeighbor];
00081             Dot3D neighbor(cellLocation.x+c[0], cellLocation.y+c[1], cellLocation.z+c[2]);
00082             // If the non-fluid node has a fluid neighbor ...
00083             if (this->isFluid(neighbor+offset)) {
00084                 // ... check how many fluid nodes it has ahead of it ...
00085                 int depth = 1;
00086                 for (int iDepth=2; iDepth<=getNumNeighbors(); ++iDepth) {
00087                     Dot3D nextNeighbor(cellLocation.x+iDepth*c[0],
00088                                        cellLocation.y+iDepth*c[1],
00089                                        cellLocation.z+iDepth*c[2]);
00090                     if (this->isFluid(nextNeighbor+offset)) {
00091                         depth = iDepth;
00092                     }
00093                     else {
00094                         break;
00095                     }
00096                 }
00097                 // ... then add this node to the list.
00098                 liquidNeighbors.push_back(std::make_pair(iNeighbor,depth));
00099                 plint iTriangle=-1;
00100                 global::timer("intersect").start();
00101                 Array<T,3> locatedPoint;
00102                 T distance;
00103                 Array<T,3> wallNormal;
00104                 Array<T,2> surfaceData;
00105                 OffBoundary::Type bdType;
00106 #ifdef PLB_DEBUG
00107                 bool ok =
00108 #endif
00109                     this->pointOnSurface (
00110                             cellLocation+offset, Dot3D(c[0],c[1],c[2]), locatedPoint, distance,
00111                             wallNormal, surfaceData, bdType, iTriangle );
00112                 global::timer("intersect").stop();
00113                 PLB_ASSERT( ok );
00114                 ids.push_back(iTriangle);
00115                 //normals.push_back(wallNormal);
00116             }
00117         }
00118         if (!liquidNeighbors.empty()) {
00119             info->getDryNodes().push_back(cellLocation);
00120             info->getDryNodeFluidDirections().push_back(liquidNeighbors);
00121             info->getDryNodeIds().push_back(ids);
00122         }
00123     }
00124 }
00125 
00126 template<typename T, template<typename U> class Descriptor>
00127 ContainerBlockData*
00128     GuoAdvDiffOffLatticeModel3D<T,Descriptor>::generateOffLatticeInfo() const
00129 {
00130     return new GuoAdvDiffOffLatticeInfo3D;
00131 }
00132 
00133 template<typename T, template<typename U> class Descriptor>
00134 void GuoAdvDiffOffLatticeModel3D<T,Descriptor>::boundaryCompletion (
00135         AtomicBlock3D& nonTypeLattice,
00136         AtomicContainerBlock3D& container,
00137             std::vector<AtomicBlock3D const*> const& args )
00138 {
00139     BlockLattice3D<T,Descriptor>& lattice =
00140         dynamic_cast<BlockLattice3D<T,Descriptor>&> (nonTypeLattice);
00141     GuoAdvDiffOffLatticeInfo3D* info =
00142         dynamic_cast<GuoAdvDiffOffLatticeInfo3D*>(container.getData());
00143     PLB_ASSERT( info );
00144     std::vector<Dot3D> const&
00145         dryNodes = info->getDryNodes();
00146     std::vector<std::vector<std::pair<int,int> > > const&
00147         dryNodeFluidDirections = info->getDryNodeFluidDirections();
00148     std::vector<std::vector<plint> > const&
00149         dryNodeIds = info->getDryNodeIds();
00150     PLB_ASSERT( dryNodes.size() == dryNodeFluidDirections.size() );
00151 
00152     Dot3D absoluteOffset = lattice.getLocation();
00153 
00154     for (pluint iDry=0; iDry<dryNodes.size(); ++iDry) {
00155         cellCompletion (
00156             lattice, dryNodes[iDry], dryNodeFluidDirections[iDry],
00157             dryNodeIds[iDry], absoluteOffset );
00158     }
00159 }
00160 
00161 template<typename T, template<typename U> class Descriptor>
00162 void GuoAdvDiffOffLatticeModel3D<T,Descriptor>::cellCompletion (
00163         BlockLattice3D<T,Descriptor>& lattice,
00164         Dot3D const& guoNode,
00165         std::vector<std::pair<int,int> > const& dryNodeFluidDirections,
00166         std::vector<plint> const& dryNodeIds, Dot3D const& absoluteOffset )
00167 {
00168     typedef Descriptor<T> D;
00169     Cell<T,Descriptor>& cell =
00170         lattice.get(guoNode.x, guoNode.y, guoNode.z);
00171     plint numDirections = (plint)dryNodeFluidDirections.size();
00172     std::vector<T> weights(numDirections);
00173     std::vector<T> rhoBar_vect(numDirections);
00174     std::vector<Array<T,Descriptor<T>::d> > jNeq_vect(numDirections);
00175     T sumWeights = T();
00176     Array<T,3> wallNormal;
00177     for (plint iDirection=0; iDirection<numDirections; ++iDirection) {
00178         int iNeighbor = dryNodeFluidDirections[iDirection].first;
00179         int const* c = NextNeighbor<T>::c[iNeighbor];
00180         Dot3D fluidDirection(c[0],c[1],c[2]);
00181         plint dryNodeId = dryNodeIds[iDirection];
00182         int depth = dryNodeFluidDirections[iDirection].second;
00183 
00184         Array<T,3> wallNode;
00185         Array<T,2> wallData;
00186         T wallDistance;
00187         OffBoundary::Type bdType;
00188 #ifdef PLB_DEBUG
00189         bool ok =
00190 #endif
00191         pointOnSurface( guoNode+absoluteOffset, fluidDirection,
00192                         wallNode, wallDistance, wallNormal,
00193                         wallData, bdType, dryNodeId );
00194         PLB_ASSERT( ok );
00195         T invDistanceToNeighbor = NextNeighbor<T>::invD[iNeighbor];
00196         PLB_ASSERT( wallDistance <= NextNeighbor<T>::d[iNeighbor] );
00197         T delta = (T)1. - wallDistance * invDistanceToNeighbor;
00198         Array<T,3> normalFluidDirection((T)fluidDirection.x, (T)fluidDirection.y, (T)fluidDirection.z);
00199         normalFluidDirection *= invDistanceToNeighbor;
00200         weights[iDirection] = util::sqr(fabs ( dot(normalFluidDirection, wallNormal) ));
00201         sumWeights += weights[iDirection];
00202 
00203         computeRhoBarJNeq (
00204                 lattice, guoNode, fluidDirection, depth,
00205                 wallNode, delta, wallData, bdType, wallNormal,
00206 
00207                 rhoBar_vect[iDirection], jNeq_vect[iDirection] );
00208     }
00209 
00210     T rhoBar = T();
00211     Array<T,D::d> jNeq; jNeq.resetToZero();
00212     for (plint iDirection=0; iDirection<numDirections; ++iDirection) {
00213         rhoBar += rhoBar_vect[iDirection] * weights[iDirection];
00214         jNeq += jNeq_vect[iDirection] * weights[iDirection];
00215     }
00216     rhoBar /= sumWeights;
00217     jNeq /= sumWeights;
00218 
00219     T dummyJsqr = T();
00220     Array<T,SymmetricTensor<T,Descriptor>::n> dummyPiNeq;
00221     
00222     Array<T,Descriptor<T>::d> j;
00223     j.from_cArray(cell.getExternal(Descriptor<T>::ExternalField::velocityBeginsAt));
00224     j *= Descriptor<T>::fullRho(rhoBar);  // At this point we got jEq.
00225     j += jNeq; // And at this point we add off-equilibrium.
00226 
00227     Dynamics<T,Descriptor> const& dynamics = cell.getDynamics();
00228     if (this->getPartialReplace()) {
00229         Cell<T,Descriptor> saveCell(cell);
00230         dynamics.regularize(cell, rhoBar, j, dummyJsqr, dummyPiNeq);
00231         for (plint iDirection=0; iDirection<numDirections; ++iDirection) {
00232             int iNeighbor = dryNodeFluidDirections[iDirection].first;
00233             plint iPop = nextNeighborPop<T,Descriptor>(iNeighbor);
00234             plint oppPop = indexTemplates::opposite<D>(iPop);
00235             cell[oppPop] = saveCell[oppPop];
00236         }
00237     }
00238     else {
00239         dynamics.regularize(cell, rhoBar, j, dummyJsqr, dummyPiNeq);
00240     }
00241 }
00242 
00243 template<typename T, template<typename U> class Descriptor>
00244 void GuoAdvDiffOffLatticeModel3D<T,Descriptor>::computeRhoBarJNeq (
00245           BlockLattice3D<T,Descriptor> const& lattice, Dot3D const& guoNode,
00246           Dot3D const& fluidDirection, int depth, Array<T,3> const& wallNode, T delta,
00247           Array<T,2> wallData, OffBoundary::Type bdType, Array<T,3> const& wallNormal,
00248           T& rhoBar, Array<T,Descriptor<T>::d>& jNeq ) const
00249 {
00250     T wall_scalar = wallData[0];
00251     T rhoBar1, rhoBar2;
00252     Array<T,Descriptor<T>::d> jNeq1, jNeq2, jEqDummy;
00253     Cell<T,Descriptor> const& cell1 =
00254         lattice.get( guoNode.x+fluidDirection.x,
00255                      guoNode.y+fluidDirection.y,
00256                      guoNode.z+fluidDirection.z );
00257     Cell<T,Descriptor> const& cell2 =
00258         lattice.get( guoNode.x+2*fluidDirection.x,
00259                      guoNode.y+2*fluidDirection.y,
00260                      guoNode.z+2*fluidDirection.z );
00261     advectionDiffusionMomentTemplates<T,Descriptor>::get_rhoBar_jEq_jNeq (
00262             cell1, rhoBar1, jEqDummy, jNeq1 );
00263     advectionDiffusionMomentTemplates<T,Descriptor>::get_rhoBar_jEq_jNeq (
00264             cell2, rhoBar2, jEqDummy, jNeq2 );
00265     T wall_rhoBar = Descriptor<T>::rhoBar(wall_scalar);
00266 
00267     if (depth < 2) {
00268         jNeq = jNeq1;
00269         if (delta < (T)0.25) {
00270             rhoBar = wall_rhoBar;
00271         }
00272         else {
00273             rhoBar = 1./delta * (wall_rhoBar+(delta-1.)*rhoBar1);
00274         }
00275     }
00276     else {  // depth >= 2
00277         if (delta < (T)0.75) {
00278             jNeq = delta*jNeq1 + ((T)1.-delta)*jNeq2;
00279             rhoBar = wall_rhoBar + (delta-(T)1.)*rhoBar1 +
00280                 ((T)1.-delta)/((T)1.+delta)*((T)2.*wall_rhoBar+(delta-(T)1.)*rhoBar2);
00281         }
00282         else {
00283             jNeq = jNeq1;
00284             rhoBar = (T)1./delta * (wall_rhoBar+(delta-(T)1.)*rhoBar1);
00285         }
00286     }
00287     if ( bdType==OffBoundary::neumann )
00288     {
00289         rhoBar = rhoBar1;
00290     }
00291     else if ( bdType==OffBoundary::flux )
00292     {
00293         T dx = sqrt(util::sqr((T)fluidDirection.x)+util::sqr((T)fluidDirection.y)+util::sqr((T)fluidDirection.z));
00294         T gradRho = wallData[0];
00295         rhoBar = rhoBar1 + dx*gradRho;
00296     }
00297     else if ( bdType==OffBoundary::isolation )
00298     {
00299         T dx = sqrt(util::sqr((T)fluidDirection.x)+util::sqr((T)fluidDirection.y)+util::sqr((T)fluidDirection.z));
00300         T rhoBarOut = Descriptor<T>::rhoBar(wallData[0]);
00301         T kappa = wallData[1];
00302         rhoBar = (rhoBar1+kappa*dx*rhoBarOut)/((T)1+kappa*dx);
00303         //pcout << "RHOBAR " << rhoBar1 << " " << rhoBarOut << " " << kappa << " " << rhoBar << std::endl;
00304     }
00305 }
00306 
00307 }  // namespace plb
00308 
00309 #endif  // GUO_ADV_DIFF_OFF_LATTICE_MODEL_3D_HH