$treeview $search $mathjax
|
Palabos
Version 1.1
$projectbrief
|
$projectbrief
|
$searchbox |
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 GENERALIZED_BOUNDARY_DYNAMICS_SOLVER_HH 00030 #define GENERALIZED_BOUNDARY_DYNAMICS_SOLVER_HH 00031 00032 #include "generalizedBoundaryDynamicsSolvers.h" 00033 #include "generalizedIncompressibleBoundaryTemplates.h" 00034 #include "core/cell.h" 00035 #include "latticeBoltzmann/indexTemplates.h" 00036 #include <Eigen3/LU> 00037 #include <Eigen3/Cholesky> 00038 00039 namespace plb { 00040 00041 // ================ GeneralizedBoundarySolver base class =================== // 00042 template<typename T, template<typename U> class Descriptor> 00043 GeneralizedBoundarySolver<T, Descriptor>::GeneralizedBoundarySolver(const std::vector<plint> &mInd_, 00044 const std::vector<plint> &kInd_) 00045 : mInd(mInd_), kInd(kInd_) 00046 { } 00047 00048 // ============ GeneralizedLinearBoundarySolver base class ================= // 00049 template<typename T, template<typename U> class Descriptor> 00050 GeneralizedLinearBoundarySolver<T, Descriptor>:: 00051 GeneralizedLinearBoundarySolver(const std::vector<plint> &mInd_, const std::vector<plint> &kInd_) 00052 : GeneralizedBoundarySolver<T, Descriptor>(mInd_,kInd_) 00053 { } 00054 00055 template<typename T, template<typename U> class Descriptor> 00056 void GeneralizedLinearBoundarySolver<T, Descriptor>::apply(Cell<T,Descriptor> &cell, const Dynamics<T,Descriptor> &dyn, 00057 bool replaceAll) { 00058 Eigen::MatrixXd A; // lhs matrix 00059 Eigen::VectorXd b, x; // rhs of system of equations, unkown of the system 00060 00061 createLinearSystem(cell, A, b); 00062 solveLinearSytem(cell, A, b, x); 00063 regularizePopulations(cell,x,dyn,replaceAll); 00064 } 00065 00066 template<typename T, template<typename U> class Descriptor> 00067 void GeneralizedLinearBoundarySolver<T, Descriptor>:: 00068 solveLinearSytem(Cell<T,Descriptor> &cell, Eigen::MatrixXd &A, Eigen::VectorXd &b, Eigen::VectorXd &x) { 00069 Eigen::MatrixXd AT = A.transpose(); 00070 A = AT * A; 00071 b = AT * b; 00072 00073 #ifdef PLB_DEBUG 00074 // bool solutionExists = A.lu().solve(b,&x); // using a LU factorization 00075 // pcout << "Error in the solution = " << (A*x-b).norm()/x.norm() << std::endl; 00076 // PLB_ASSERT(solutionExists); 00077 00078 x = A.fullPivLu().solve(b); 00079 T relError = (A*x - b).norm() / b.norm(); 00080 PLB_ASSERT(relError < 1.0e-12); 00081 00082 #else 00083 x = A.fullPivLu().solve(b); 00084 // A.lu().solve(b,&x); 00085 #endif 00086 } 00087 00088 // =========== GeneralizedNonLinearBoundarySolver base class =============== // 00089 00090 template<typename T, template<typename U> class Descriptor> 00091 GeneralizedNonLinearBoundarySolver<T, Descriptor>:: 00092 GeneralizedNonLinearBoundarySolver(const std::vector<plint> &mInd_, const std::vector<plint> &kInd_, 00093 T epsilon_) 00094 : GeneralizedBoundarySolver<T, Descriptor>(mInd_,kInd_), epsilon(epsilon_) 00095 { } 00096 00097 template<typename T, template<typename U> class Descriptor> 00098 bool GeneralizedNonLinearBoundarySolver<T, Descriptor>::converge(const Eigen::VectorXd &x, const Eigen::VectorXd &dx) { 00099 for (plint iPi = 0; iPi < x.rows(); ++iPi) { 00100 T res = (fabs(x[iPi]) > 1.0e-14 ? fabs(dx(iPi)/x(iPi)) : fabs(x(iPi))); 00101 00102 if (res > epsilon) return false; 00103 } 00104 return true; 00105 } 00106 00107 template<typename T, template<typename U> class Descriptor> 00108 void GeneralizedNonLinearBoundarySolver<T, Descriptor>:: 00109 iterateNonLinearSystem(const Eigen::MatrixXd &Jac, const Eigen::VectorXd &f, 00110 Eigen::VectorXd &x, Eigen::VectorXd &dx) { 00111 Eigen::MatrixXd JacT = Jac.transpose(); 00112 Eigen::MatrixXd JacSqr = JacT * Jac; 00113 Eigen::VectorXd JacTf = JacT * f; 00114 00115 #ifdef PLB_DEBUG 00116 // bool solutionExists = JacSqr.lu().solve(JacTf,&dx); // using a LU factorization 00117 // PLB_ASSERT(solutionExists); 00118 x = JacSqr.fullPivLu().solve(JacT); 00119 T relError = (JacSqr*x - JacT).norm() / JacT.norm(); 00120 PLB_ASSERT(relError < 1.0e-12); 00121 #else 00122 x = JacSqr.fullPivLu().solve(JacT); 00123 // JacSqr.lu().solve(JacTf,&dx); 00124 #endif 00125 00126 T stepMult = (T)1; // step size (step mult can only be <= 1 (usually = 1). 00127 x += stepMult*dx; // increment solution 00128 } 00129 00130 template<typename T, template<typename U> class Descriptor> 00131 void GeneralizedNonLinearBoundarySolver<T, Descriptor>::apply(Cell<T,Descriptor> &cell, 00132 const Dynamics<T,Descriptor> &dyn, 00133 bool replaceAll) { 00134 Eigen::MatrixXd Jacobian; // lhs matrix 00135 Eigen::VectorXd f, x, dx; // rhs of system of equations, unkown of the system 00136 00137 plint maxT = 10000; 00138 iniSystem(Jacobian, f, x, dx); 00139 fromMacroToX(x); 00140 for (plint iT = 0; iT < maxT; ++iT) { 00141 createNonLinearSystem(cell, Jacobian, f); 00142 iterateNonLinearSystem(Jacobian, f, x, dx); 00143 fromXtoMacro(x); 00144 if (converge(x,dx)) { 00145 break; 00146 } 00147 } 00148 00149 regularizePopulations(cell,x,dyn,replaceAll); 00150 00151 } 00152 00153 // ========================================================================= // 00154 // ============ Different kind of Linear BCs for incompressible fluids ===== // 00155 // ========================================================================= // 00156 00157 // ========================= Dirichlet Velocity BC ========================= // 00158 // ======================= without mass conservation ======================= // 00159 00160 template<typename T, template<typename U> class Descriptor> 00161 DirichletVelocityBoundarySolver<T,Descriptor>:: 00162 DirichletVelocityBoundarySolver(const std::vector<plint> &mInd_, const std::vector<plint> &kInd_, 00163 const Array<T,Descriptor<T>::d> &u_) : 00164 GeneralizedLinearBoundarySolver<T, Descriptor>(mInd_,kInd_), u(u_) 00165 { 00166 sysX = SymmetricTensor<T,Descriptor>::n+1; 00167 sysY = this->kInd.size()+1; 00168 } 00169 00170 template<typename T, template<typename U> class Descriptor> 00171 void DirichletVelocityBoundarySolver<T,Descriptor>:: 00172 createLinearSystem(Cell<T,Descriptor> &cell, Eigen::MatrixXd &A, Eigen::VectorXd &b) { 00173 00174 // matrix of the system Ax=b 00175 A = Eigen::MatrixXd::Zero(sysY,sysX); 00176 // rhs of the equation Ax=b 00177 b = Eigen::VectorXd::Zero(sysY); 00178 00179 T uSqr = VectorTemplate<T,Descriptor>::normSqr(u); 00180 // f^k = A * x 00181 // A = g, 1/(2c_s^4) H^2 00182 // with g being feq/rho and H^2 the second order Hermite polynomial 00183 generalizedIncomprBoundaryTemplates<T,Descriptor>::f_to_A_ma2_contrib(this->kInd,u,uSqr,A); 00184 generalizedIncomprBoundaryTemplates<T,Descriptor>::f_to_b_contrib(cell,this->kInd,b); 00185 00186 T rhoTmp = T(); 00187 for (pluint fInd = 0; fInd < this->kInd.size(); ++fInd) { 00188 plint iPop = this->kInd[fInd]; 00189 rhoTmp += fullF<T,Descriptor>(cell[iPop], iPop); 00190 } 00191 // rhoTtmp = sum_i->known f_i. 00192 b[sysY-1] = rhoTmp; 00193 00194 // first row of the A matrix. imposing sum_i f_i = rho. 00195 Eigen::RowVectorXd e0 = Eigen::RowVectorXd::Zero(sysX); 00196 e0[0] = 1.0; 00197 00198 Eigen::RowVectorXd sumA = Eigen::RowVectorXd::Zero(sysX); 00199 for (pluint fInd = 0; fInd < this->mInd.size(); ++fInd) { 00200 plint iPop = this->mInd[fInd]; 00201 Eigen::RowVectorXd lineA = Eigen::RowVectorXd::Zero(sysX); 00202 generalizedIncomprBoundaryTemplates<T,Descriptor>::f_ma2_linear(iPop, u, uSqr, lineA); 00203 for (plint iVec = 0; iVec < sysX; ++iVec) sumA(iVec) += lineA(iVec); 00204 } 00205 00206 A.row(sysY-1) = e0-sumA; 00207 } 00208 00209 template<typename T, template<typename U> class Descriptor> 00210 void DirichletVelocityBoundarySolver<T,Descriptor>:: 00211 regularizePopulations(Cell<T,Descriptor> &cell, const Eigen::VectorXd &x, 00212 const Dynamics<T,Descriptor> &dyn, bool replaceAll ) { 00213 00214 T rho; 00215 Array<T,SymmetricTensor<T,Descriptor>::n> PiNeq; 00216 generalizedIncomprBoundaryTemplates<T,Descriptor>::fromXtoRhoAndPiNeq(x, rho, PiNeq); 00217 T rhoBar = Descriptor<T>::rhoBar(rho); 00218 Array<T,Descriptor<T>::d> j = rho * u; 00219 T jSqr = VectorTemplate<T,Descriptor>::normSqr(j); 00220 if (replaceAll) { 00221 dyn.regularize(cell, rhoBar, j, jSqr, PiNeq); 00222 } else { 00223 Cell<T,Descriptor> tmpCell; 00224 dyn.regularize(tmpCell, rhoBar, j, jSqr, PiNeq); 00225 for (pluint fInd = 0; fInd < this->mInd.size(); ++fInd) { 00226 plint iPop = this->mInd[fInd]; 00227 cell[iPop] = tmpCell[iPop]; 00228 } 00229 } 00230 } 00231 00232 // ========================= Dirichlet Velocity BC ========================= // 00233 // ======================= with mass conservation ======================= // 00234 00235 template<typename T, template<typename U> class Descriptor> 00236 DirichletMassConservingVelocityBoundarySolver<T,Descriptor>:: 00237 DirichletMassConservingVelocityBoundarySolver(const std::vector<plint> &mInd_, 00238 const std::vector<plint> &kInd_, 00239 const std::vector<plint> &inGoingInd_, 00240 const Array<T,Descriptor<T>::d> &u_ ) : 00241 GeneralizedLinearBoundarySolver<T, Descriptor>(mInd_,kInd_), 00242 inGoingInd(inGoingInd_), u(u_) 00243 { 00244 sysX = SymmetricTensor<T,Descriptor>::n+1; 00245 sysY = this->kInd.size()+1; 00246 } 00247 00248 template<typename T, template<typename U> class Descriptor> 00249 void DirichletMassConservingVelocityBoundarySolver<T,Descriptor>:: 00250 createLinearSystem(Cell<T,Descriptor> &cell, Eigen::MatrixXd &A, Eigen::VectorXd &b) { 00251 00252 // matrix of the system Ax=b 00253 A = Eigen::MatrixXd::Zero(sysY,sysX); 00254 // rhs of the equation Ax=b 00255 b = Eigen::VectorXd::Zero(sysY); 00256 00257 T uSqr = VectorTemplate<T,Descriptor>::normSqr(u); 00258 // f^k = A * x 00259 // A = g, 1/(2c_s^4) H^2 00260 // with g being feq/rho and H^2 the second order Hermite polynomial 00261 00262 generalizedIncomprBoundaryTemplates<T,Descriptor>::f_to_A_ma2_contrib(this->kInd,u,uSqr,A); 00263 generalizedIncomprBoundaryTemplates<T,Descriptor>::f_to_b_contrib(cell,this->kInd,b); 00264 00265 // computing mass incoming in the wall 00266 T rhoTmp = T(); 00267 for (pluint fInd = 0; fInd < this->inGoingInd.size(); ++fInd) { 00268 plint iPop = indexTemplates::opposite<Descriptor<T> >(inGoingInd[fInd]); 00269 rhoTmp += fullF<T,Descriptor>(cell[iPop], iPop); 00270 } 00271 // rhoTtmp = sum_i->in_wall f_i. 00272 b[sysY-1] = rhoTmp; 00273 00274 const T omega = cell.getDynamics().getOmega(); 00275 Eigen::RowVectorXd sumA = Eigen::RowVectorXd::Zero(sysX); 00276 for (pluint fInd = 0; fInd < inGoingInd.size(); ++fInd) { 00277 plint iPop = inGoingInd[fInd]; 00278 Eigen::RowVectorXd lineA = Eigen::RowVectorXd::Zero(sysX); 00279 generalizedIncomprBoundaryTemplates<T,Descriptor>::f_ma2_linear(iPop, u, uSqr, lineA, omega); 00280 for (plint iVec = 0; iVec < sysX; ++iVec) sumA(iVec) += lineA(iVec); 00281 } 00282 00283 A.row(sysY-1) = sumA; 00284 } 00285 00286 template<typename T, template<typename U> class Descriptor> 00287 void DirichletMassConservingVelocityBoundarySolver<T,Descriptor>:: 00288 regularizePopulations(Cell<T,Descriptor> &cell, const Eigen::VectorXd &x, 00289 const Dynamics<T,Descriptor> &dyn, bool replaceAll ) { 00290 00291 T rho; 00292 Array<T,SymmetricTensor<T,Descriptor>::n> PiNeq; 00293 generalizedIncomprBoundaryTemplates<T,Descriptor>::fromXtoRhoAndPiNeq(x, rho, PiNeq); 00294 T rhoBar = Descriptor<T>::rhoBar(rho); 00295 Array<T,Descriptor<T>::d> j = rho * u; 00296 T jSqr = VectorTemplate<T,Descriptor>::normSqr(j); 00297 dyn.regularize(cell, rhoBar, j, jSqr, PiNeq); 00298 } 00299 00300 // ========================================================================= // 00301 // ======== Different kind of Non Linear BCs for incompressible fluids ===== // 00302 // ========================================================================= // 00303 00304 // ========================= Dirichlet Density BC ========================= // 00305 template<typename T, template<typename U> class Descriptor, int dir> 00306 DirichletDensityBoundarySolver<T,Descriptor,dir>:: 00307 DirichletDensityBoundarySolver(const std::vector<plint> &mInd_, const std::vector<plint> &kInd_, 00308 T &rho_, Array<T,Descriptor<T>::d> &u_, 00309 Array<T,SymmetricTensor<T,Descriptor>::n> &PiNeq_, 00310 T epsilon_) : 00311 GeneralizedNonLinearBoundarySolver<T, Descriptor>(mInd_,kInd_, epsilon_) 00312 { 00313 sysX = SymmetricTensor<T,Descriptor>::n+1; 00314 sysY = this->kInd.size(); 00315 00316 this->macro.push_back(rho_); 00317 for (plint iD = 0; iD < Descriptor<T>::d; ++iD) this->macro.push_back(u_[iD]); 00318 for (plint iPi = 0; iPi < SymmetricTensor<T,Descriptor>::n; ++iPi) this->macro.push_back(PiNeq_[iPi]); 00319 } 00320 00321 template<typename T, template<typename U> class Descriptor, int dir> 00322 void DirichletDensityBoundarySolver<T,Descriptor,dir>::fromMacroToX(Eigen::VectorXd &x) { 00323 x[0] = this->macro[1+dir]; 00324 for (plint iPi = 0; iPi < SymmetricTensor<T,Descriptor>::n; ++iPi) { 00325 x[iPi+1] = this->macro[1+Descriptor<T>::d+iPi]; 00326 } 00327 } 00328 00329 template<typename T, template<typename U> class Descriptor, int dir> 00330 void DirichletDensityBoundarySolver<T,Descriptor,dir>::fromXtoMacro(const Eigen::VectorXd &x) { 00331 this->macro[1+dir] = x[0]; 00332 for (plint iPi = 0; iPi < SymmetricTensor<T,Descriptor>::n; ++iPi) { 00333 this->macro[1+Descriptor<T>::d+iPi] = x[iPi+1]; 00334 } 00335 } 00336 00337 template<typename T, template<typename U> class Descriptor, int dir> 00338 void DirichletDensityBoundarySolver<T,Descriptor,dir>:: 00339 iniSystem(Eigen::MatrixXd &Jac, Eigen::VectorXd &f, 00340 Eigen::VectorXd &x, Eigen::VectorXd &dx) { 00341 00342 Jac = Eigen::MatrixXd::Zero(sysY,sysX); 00343 f = Eigen::VectorXd::Zero(sysY); // stores the non-linear function 00344 x = Eigen::VectorXd::Zero(sysX); // stores the variables (u[dir] and PiNeq) 00345 dx = Eigen::VectorXd::Zero(sysX); // contains delta_u[dir], delta_PiNeq (the increments towards the solution) 00346 } 00347 00348 template<typename T, template<typename U> class Descriptor, int dir> 00349 void DirichletDensityBoundarySolver<T,Descriptor,dir>:: 00350 createNonLinearSystem(const Cell<T,Descriptor> &cell, Eigen::MatrixXd &Jac, Eigen::VectorXd &f) { 00351 00352 // computes the non linear function F(macro) = f_i-(f^eq+f^1) 00353 T rho; 00354 Array<T,Descriptor<T>::d> j; 00355 Array<T,SymmetricTensor<T,Descriptor>::n> PiNeq; 00356 generalizedIncomprBoundaryTemplates<T,Descriptor>:: 00357 from_macro_to_rho_j_pineq(this->macro, rho, j, PiNeq); 00358 00359 T rhoBar = Descriptor<T>::rhoBar(rho); 00360 T invRho = Descriptor<T>::invRho(rhoBar); 00361 T jSqr = VectorTemplate<T,Descriptor>::normSqr(j); 00362 for (pluint iPop = 0; iPop < this->kInd.size(); ++iPop) { 00363 f[iPop] = cell[this->kInd[iPop]] - ( 00364 dynamicsTemplates<T,Descriptor>::bgk_ma2_equilibrium(this->kInd[iPop], rhoBar, invRho, j, jSqr) + 00365 offEquilibriumTemplates<T,Descriptor>::fromPiToFneq(this->kInd[iPop],PiNeq) ); 00366 } 00367 00368 // computes the Jacobian of F(macro) 00369 Eigen::RowVectorXd df = Eigen::RowVectorXd::Zero(sysX); 00370 for (pluint iPop = 0; iPop < this->kInd.size(); ++iPop) { 00371 generalizedIncomprBoundaryTemplates<T,Descriptor>:: 00372 compute_f_diff_u_dir_and_PiNeq(this->kInd[iPop], rho, j*invRho, df, dir); 00373 Jac.row(iPop) = df; 00374 } 00375 } 00376 00377 template<typename T, template<typename U> class Descriptor, int dir> 00378 void DirichletDensityBoundarySolver<T,Descriptor,dir>:: 00379 regularizePopulations(Cell<T,Descriptor> &cell, const Eigen::VectorXd &x, 00380 const Dynamics<T,Descriptor> &dyn, bool replaceAll ) { 00381 00382 T rho; 00383 Array<T,Descriptor<T>::d> j; 00384 Array<T,SymmetricTensor<T,Descriptor>::n> PiNeq; 00385 generalizedIncomprBoundaryTemplates<T,Descriptor>:: 00386 from_macro_to_rho_j_pineq(this->macro, rho, j, PiNeq); 00387 00388 T rhoBar = Descriptor<T>::rhoBar(rho); 00389 T jSqr = VectorTemplate<T,Descriptor>::normSqr(j); 00390 if (replaceAll) { 00391 dyn.regularize(cell, rhoBar, j, jSqr, PiNeq); 00392 } 00393 else { 00394 Cell<T,Descriptor> tmpCell; 00395 dyn.regularize(tmpCell, rhoBar, j, jSqr, PiNeq); 00396 for (pluint fInd = 0; fInd < this->mInd.size(); ++fInd) { 00397 plint iPop = this->mInd[fInd]; 00398 cell[iPop] = tmpCell[iPop]; 00399 } 00400 } 00401 } 00402 00403 00404 00405 } // namespace plb 00406 00407 #endif // GENERALIZED_BOUNDARY_DYNAMICS_HH
1.6.3
1.6.3