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

thermalDynamics.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 
00029 #ifndef THERMAL_DYNAMICS_HH
00030 #define THERMAL_DYNAMICS_HH
00031 
00032 #include <algorithm>
00033 #include <limits>
00034 #include "basicDynamics/thermalDynamics.h"
00035 #include "core/cell.h"
00036 #include "latticeBoltzmann/dynamicsTemplates.h"
00037 #include "latticeBoltzmann/momentTemplates.h"
00038 #include "latticeBoltzmann/externalForceTemplates.h"
00039 #include "latticeBoltzmann/offEquilibriumTemplates.h"
00040 #include "latticeBoltzmann/d3q13Templates.h"
00041 #include "latticeBoltzmann/geometricOperationTemplates.h"
00042 #include "core/latticeStatistics.h"
00043 
00044 namespace plb {
00045 
00046 /* *************** Class ThermalBulkDynamics ************************************ */
00047 
00048 template<typename T, template<typename U> class Descriptor>
00049 ThermalBulkDynamics<T,Descriptor>::ThermalBulkDynamics(T omega_)
00050   : BasicBulkDynamics<T,Descriptor>(omega_)
00051 { }
00052 
00053 template<typename T, template<typename U> class Descriptor>
00054 void ThermalBulkDynamics<T,Descriptor>::regularize (
00055         Cell<T,Descriptor>& cell, T rhoBar, Array<T,Descriptor<T>::d> const& j,
00056         T jSqr, Array<T,SymmetricTensor<T,Descriptor>::n> const& PiNeq, T thetaBar ) const
00057 {
00058     
00059     Array<T,SymmetricRankThreeTensor<T,Descriptor>::n> qNeq;
00060     momentTemplates<T,Descriptor>::compute_Qneq(cell, rhoBar, j,thetaBar,qNeq );
00061     
00062     typedef Descriptor<T> L;
00063     for (plint iPop=0; iPop < L::q; ++iPop) {
00064         cell[iPop] = computeEquilibrium(iPop, rhoBar, j, jSqr, thetaBar);
00065         T fNeq = offEquilibriumTemplatesImpl<T,L>::fromPiAndQtoFneq(iPop, PiNeq, qNeq);
00066         cell[iPop] += fNeq;
00067     }
00068 }
00069 
00070 template<typename T, template<typename U> class Descriptor>
00071 T ThermalBulkDynamics<T,Descriptor>::computeTemperature(Cell<T,Descriptor> const& cell) const
00072 {
00073     T rhoBar;
00074     Array<T,Descriptor<T>::d> j;
00075     computeRhoBarJ(cell,rhoBar,j);
00076     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00077     return momentTemplates<T,Descriptor>::compute_theta(cell, rhoBar, jSqr);
00078 }
00079 
00080 template<typename T, template<typename U> class Descriptor>
00081 void ThermalBulkDynamics<T,Descriptor>::computeDeviatoricStress (
00082     Cell<T,Descriptor> const& cell, Array<T,SymmetricTensor<T,Descriptor>::n>& PiNeq ) const
00083 {
00084     T rhoBar;
00085     Array<T,Descriptor<T>::d> j;
00086     computeRhoBarJ(cell,rhoBar,j);
00087     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00088     T thetaBar = momentTemplates<T,Descriptor>::compute_theta(cell, rhoBar, jSqr)-(T)1;
00089     momentTemplates<T,Descriptor>::compute_thermal_PiNeq(cell, rhoBar, thetaBar, j, PiNeq);
00090 }
00091 
00092 template<typename T, template<typename U> class Descriptor>
00093 void ThermalBulkDynamics<T,Descriptor>::computeHeatFlux (
00094         Cell<T,Descriptor> const& cell, Array<T,Descriptor<T>::d>& q ) const
00095 {
00096     T rhoBar;
00097     Array<T,Descriptor<T>::d> j;
00098     computeRhoBarJ(cell,rhoBar,j);
00099     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00100     T thetaBar = momentTemplates<T,Descriptor>::compute_theta(cell, rhoBar, jSqr)-(T)1;
00101     momentTemplates<T,Descriptor>::compute_heat_flux(cell, rhoBar, j,thetaBar,q );
00102 }
00103 
00104 template<typename T, template<typename U> class Descriptor>
00105 T ThermalBulkDynamics<T,Descriptor>::computeEbar(Cell<T,Descriptor> const& cell) const
00106 {
00107     return momentTemplates<T,Descriptor>::get_eBar(cell);
00108 }
00109 
00110 // TODO needs to be extended from iso-thermal to thermal case
00111 template<typename T, template<typename U> class Descriptor>
00112 plint ThermalBulkDynamics<T,Descriptor>::numDecomposedVariables(plint order) const {
00113     plint numVariables =
00114                          // Order 0: density + velocity + fNeq
00115         ( order == 0 ) ? ( 1 + Descriptor<T>::d + 1 + Descriptor<T>::q ) // rhoBar, j, thetaBar, fNeq
00116                          // Order >=1: density + velocity + PiNeq
00117                          : ( 1 + Descriptor<T>::d + 1 + SymmetricTensor<T,Descriptor>::n + SymmetricRankThreeTensor<T,Descriptor>::n); // rhoBar, j, thetaBar, piNeq, qNeq
00118 
00119     numVariables += Descriptor<T>::ExternalField::numScalars;
00120     return numVariables;
00121 }
00122 
00123 // TODO needs to be extended from iso-thermal to thermal case
00124 template<typename T, template<typename U> class Descriptor>
00125 void ThermalBulkDynamics<T,Descriptor>::decompose (
00126         Cell<T,Descriptor> const& cell, std::vector<T>& rawData, plint order ) const
00127 {
00128     rawData.resize(numDecomposedVariables(order));
00129 
00130     if (order==0) {
00131         decomposeOrder0(cell, rawData);
00132     }
00133     else {
00134         decomposeOrder1(cell, rawData);
00135     }
00136 }
00137 
00138 // TODO needs to be extended from iso-thermal to thermal case
00139 template<typename T, template<typename U> class Descriptor>
00140 void ThermalBulkDynamics<T,Descriptor>::recompose (
00141         Cell<T,Descriptor>& cell, std::vector<T> const& rawData, plint order ) const
00142 {
00143     PLB_PRECONDITION( (plint) rawData.size() == numDecomposedVariables(order) );
00144 
00145     if (order==0) {
00146         recomposeOrder0(cell, rawData);
00147     }
00148     else {
00149         recomposeOrder1(cell, rawData);
00150     }
00151 }
00152 
00153 // TODO needs to be extended from iso-thermal to thermal case
00154 template<typename T, template<typename U> class Descriptor>
00155 void ThermalBulkDynamics<T,Descriptor>::rescale (
00156         std::vector<T>& rawData, T xDxInv, T xDt, plint order ) const
00157 {
00158     PLB_PRECONDITION( (plint) rawData.size()==numDecomposedVariables(order) );
00159 
00160     if (order==0) {
00161         rescaleOrder0(rawData, xDxInv, xDt);
00162     }
00163     else {
00164         rescaleOrder1(rawData, xDxInv, xDt);
00165     }
00166 }
00167 
00168 template<typename T, template<typename U> class Descriptor>
00169 void ThermalBulkDynamics<T,Descriptor>::decomposeOrder0 (
00170         Cell<T,Descriptor> const& cell, std::vector<T>& rawData ) const
00171 {
00172     T rhoBar, thetaBar;
00173     Array<T,Descriptor<T>::d> j;
00174     momentTemplates<T,Descriptor>::get_rhoBar_j_thetaBar(cell, rhoBar, j, thetaBar);
00175     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00176     rawData[0] = rhoBar;
00177     j.to_cArray(&rawData[1]);
00178     rawData[1+Descriptor<T>::d] = thetaBar;
00179     
00180     for (plint iPop=0; iPop<Descriptor<T>::q; ++iPop) {
00181         rawData[2+Descriptor<T>::d+iPop] =
00182         cell[iPop] - this->computeEquilibrium(iPop, rhoBar, j, jSqr);
00183     }
00184     
00185     int offset = 2+Descriptor<T>::d+Descriptor<T>::q;
00186     for (plint iExt=0; iExt<Descriptor<T>::ExternalField::numScalars; ++iExt) {
00187         rawData[offset+iExt] = *cell.getExternal(iExt);
00188     }
00189 }
00190 
00191 template<typename T, template<typename U> class Descriptor>
00192 void ThermalBulkDynamics<T,Descriptor>::decomposeOrder1 (
00193         Cell<T,Descriptor> const& cell, std::vector<T>& rawData ) const
00194 {
00195     T rhoBar, thetaBar;
00196     Array<T,Descriptor<T>::d> j;
00197     Array<T,SymmetricTensor<T,Descriptor>::n> PiNeq;
00198     Array<T,SymmetricRankThreeTensor<T,Descriptor>::n> qNeq;
00199     momentTemplates<T,Descriptor>::compute_rhoBar_thetaBar_j_PiNeq_qNeq(cell, rhoBar, thetaBar, j, PiNeq, qNeq);
00200     
00201     rawData[0] = rhoBar;
00202     j.to_cArray(&rawData[1]);
00203     rawData[1+Descriptor<T>::d] = thetaBar;
00204     PiNeq.to_cArray(&rawData[2+Descriptor<T>::d]);
00205     qNeq.to_cArray(&rawData[2+Descriptor<T>::d+SymmetricTensor<T,Descriptor>::n+SymmetricRankThreeTensor<T,Descriptor>::n]);
00206     
00207     int offset = 2+Descriptor<T>::d+SymmetricTensor<T,Descriptor>::n+SymmetricRankThreeTensor<T,Descriptor>::n;
00208     for (plint iExt=0; iExt<Descriptor<T>::ExternalField::numScalars; ++iExt) {
00209         rawData[offset+iExt] = *cell.getExternal(iExt);
00210     }
00211 }
00212 
00213 template<typename T, template<typename U> class Descriptor>
00214 void ThermalBulkDynamics<T,Descriptor>::recomposeOrder0 (
00215         Cell<T,Descriptor>& cell, std::vector<T> const& rawData ) const
00216 {
00217     T rhoBar = rawData[0];
00218     Array<T,Descriptor<T>::d> j;
00219     j.from_cArray(&rawData[1]);
00220     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00221     T thetaBar = rawData[1+Descriptor<T>::d];
00222     
00223     for (plint iPop=0; iPop<Descriptor<T>::q; ++iPop) {
00224         cell[iPop] = this->computeEquilibrium(iPop, rhoBar, j, jSqr, thetaBar)
00225         + rawData[2+Descriptor<T>::d+iPop];
00226     }
00227     
00228     int offset = 2+Descriptor<T>::d+Descriptor<T>::q;
00229     for (plint iExt=0; iExt<Descriptor<T>::ExternalField::numScalars; ++iExt) {
00230         *cell.getExternal(iExt) = rawData[offset+iExt];
00231     }
00232 }
00233 
00234 template<typename T, template<typename U> class Descriptor>
00235 void ThermalBulkDynamics<T,Descriptor>::recomposeOrder1 (
00236         Cell<T,Descriptor>& cell, std::vector<T> const& rawData ) const
00237 {
00238     typedef Descriptor<T> L;
00239     
00240     T rhoBar, thetaBar;
00241     Array<T,Descriptor<T>::d> j;
00242     Array<T,SymmetricTensor<T,Descriptor>::n> PiNeq;
00243     Array<T,SymmetricRankThreeTensor<T,Descriptor>::n> qNeq;
00244     
00245     rhoBar = rawData[0];
00246     j.from_cArray(&rawData[1]);
00247     thetaBar = rawData[1+Descriptor<T>::d];
00248     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00249     PiNeq.from_cArray(&rawData[2+Descriptor<T>::d]);
00250     qNeq.from_cArray(&rawData[2+Descriptor<T>::d+SymmetricTensor<T,Descriptor>::n]);
00251     
00252     for (plint iPop=0; iPop<L::q; ++iPop) {
00253         cell[iPop] = this->computeEquilibrium(0, rhoBar, j, jSqr, thetaBar)
00254             + offEquilibriumTemplates<T,Descriptor>::fromPiAndQtoFneq(0, PiNeq, qNeq);
00255     }
00256     
00257     int offset = 2+Descriptor<T>::d+SymmetricTensor<T,Descriptor>::n;
00258     for (plint iExt=0; iExt<Descriptor<T>::ExternalField::numScalars; ++iExt) {
00259         *cell.getExternal(iExt) = rawData[offset+iExt];
00260     }
00261 }
00262 
00263 template<typename T, template<typename U> class Descriptor>
00264 void ThermalBulkDynamics<T,Descriptor>::rescaleOrder0 (
00265         std::vector<T>& rawData, T xDxInv, T xDt ) const
00266 {
00267     // Don't change rho (rawData[0]), because it is invariant
00268 
00269     // Change velocity, according to its units dx/dt
00270     T velScale = xDt * xDxInv;
00271     for (plint iVel=0; iVel<Descriptor<T>::d; ++iVel) {
00272         rawData[1+iVel] *= velScale;
00273     }
00274 
00275     // Change off-equilibrium, according to its units 1/dt
00276     T fNeqScale = xDt;
00277     for (plint iFneq=0; iFneq<Descriptor<T>::q; ++iFneq) {
00278         rawData[1+Descriptor<T>::d+iFneq] *= fNeqScale;
00279     }
00280 
00281     // Don't change external fields; their scaling must be taken care of
00282     //   in specialized versions of this class.
00283 }
00284 
00285 template<typename T, template<typename U> class Descriptor>
00286 void ThermalBulkDynamics<T,Descriptor>::rescaleOrder1 (
00287         std::vector<T>& rawData, T xDxInv, T xDt ) const
00288 {
00289     // Don't change rho (rawData[0]), because it is invariant
00290 
00291     // Change velocity, according to its units dx/dt
00292     T velScale = xDt * xDxInv;
00293     for (plint iVel=0; iVel<Descriptor<T>::d; ++iVel) {
00294         rawData[1+iVel] *= velScale;
00295     }
00296 
00297     // Change off-equilibrium stress, according to its units 1/dt
00298     T PiNeqScale = xDt;
00299     for (plint iPi=0; iPi<SymmetricTensor<T,Descriptor>::n; ++iPi) {
00300         rawData[1+Descriptor<T>::d+iPi] *= PiNeqScale;
00301     }
00302 
00303     // Don't change external fields; their scaling must be taken care of
00304     //   in specialized versions of this class.
00305 }
00306 
00307 /* *************** Class ThermalBGKdynamics *********************************************** */
00308 
00309 template<typename T, template<typename U> class Descriptor>
00310 int ThermalBGKdynamics<T,Descriptor>::id =
00311     meta::registerOneParamDynamics<T,Descriptor,ThermalBGKdynamics<T,Descriptor> >("BGK_Thermal");
00312 
00315 template<typename T, template<typename U> class Descriptor>
00316 ThermalBGKdynamics<T,Descriptor>::ThermalBGKdynamics(T omega_ ) : ThermalBulkDynamics<T,Descriptor>(omega_)
00317 { }
00318 
00319 template<typename T, template<typename U> class Descriptor>
00320 ThermalBGKdynamics<T,Descriptor>* ThermalBGKdynamics<T,Descriptor>::clone() const {
00321     return new ThermalBGKdynamics<T,Descriptor>(*this);
00322 }
00323 
00324 template<typename T, template<typename U> class Descriptor>
00325 int ThermalBGKdynamics<T,Descriptor>::getId() const {
00326     return id;
00327 }
00328 
00329 template<typename T, template<typename U> class Descriptor>
00330 T ThermalBGKdynamics<T,Descriptor>::
00331     computeEquilibrium(plint iPop, T rhoBar, Array<T,Descriptor<T>::d> const& j,
00332                        T jSqr, T thetaBar) const {
00333                            
00334     T invRho = Descriptor<T>::invRho(rhoBar);
00335     T rhoThetaBar = Descriptor<T>::fullRho(rhoBar)*thetaBar; // thetaBar = theta - 1
00336     return dynamicsTemplates<T,Descriptor>::bgk_ma4_equilibrium(iPop, rhoBar, invRho, j, jSqr, rhoThetaBar);
00337 }
00338 
00339 template<typename T, template<typename U> class Descriptor>
00340 void ThermalBGKdynamics<T,Descriptor>::collide (
00341         Cell<T,Descriptor>& cell,
00342         BlockStatistics& statistics )
00343 {
00344     T rhoBar;
00345     Array<T,Descriptor<T>::d> j;
00346     computeRhoBarJ(cell,rhoBar,j);
00347     T jSqr = VectorTemplate<T,Descriptor>::normSqr(j);
00348     T rhoThetaBar = momentTemplates<T,Descriptor>::compute_rhoThetaBar(cell,rhoBar,jSqr);
00349     
00350     T uSqr = dynamicsTemplates<T,Descriptor>::bgk_ma4_collision(cell, rhoBar, j, rhoThetaBar, this->getOmega());
00351     
00352     if (cell.takesStatistics()) {
00353         gatherStatistics(statistics, rhoBar, uSqr);
00354     }
00355 }
00356 
00357 
00358 }
00359 
00360 #endif