/* This file is part of the OpenLB library * * Copyright (C) 2017-2019 Albert Mink, Christopher McHardy * E-mail contact: info@openlb.net * The most recent release of OpenLB can be downloaded at * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** \file * A collection of radiative transport dynamics classes -- generic implementation. */ #ifndef RTLBM_DYNAMICS_HH #define RTLBM_DYNAMICS_HH #include "rtlbmDynamics.h" #include "rtlbmDescriptors.h" #include "lbHelpers.h" namespace olb { //==================================================================// //============= BGK Model for Advection diffusion anisotropic ===// //==================================================================// template RTLBMdynamicsMcHardy::RTLBMdynamicsMcHardy (Momenta& momenta, T latticeAbsorption, T latticeScattering, std::array, DESCRIPTOR::q>& anisoMatrix) : BasicDynamics(momenta), _absorption(latticeAbsorption), _scattering(latticeScattering), _anisoMatrix(anisoMatrix) { } template T RTLBMdynamicsMcHardy::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr ) const { return lbHelpers::equilibriumFirstOrder( iPop, rho, u ); } template void RTLBMdynamicsMcHardy::collide( Cell& cell, LatticeStatistics& statistics ) { std::array feq = {}; for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) { for ( int jPop = 0; jPop < DESCRIPTOR::q; ++jPop ) { feq[iPop] += (cell[jPop] + descriptors::t(jPop)) * _anisoMatrix[jPop][iPop]; } feq[iPop] *= descriptors::t(iPop); } // execute collision for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = (cell[iPop]+descriptors::t(iPop)) - descriptors::norm_c(iPop)*(_absorption+_scattering) * ( (cell[iPop]+descriptors::t(iPop))- feq[iPop] ) - _absorption*descriptors::norm_c(iPop) *(cell[iPop]+descriptors::t(iPop)) - descriptors::t(iPop); } T temperature = lbHelpers::computeRho(cell); statistics.incrementStats( temperature, T() ); } template T RTLBMdynamicsMcHardy::getOmega() const { return -1; } template void RTLBMdynamicsMcHardy::setOmega( T omega ) { } //==================================================================================// template RTLBMdynamicsMcHardyRK::RTLBMdynamicsMcHardyRK (Momenta& momenta, T latticeAbsorption, T latticeScattering, std::array, DESCRIPTOR::q>& anisoMatrix) : BasicDynamics(momenta), _absorption(latticeAbsorption), _scattering(latticeScattering), _anisoMatrix(anisoMatrix) { } template T RTLBMdynamicsMcHardyRK::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr ) const { return lbHelpers::equilibriumFirstOrder( iPop, rho, u ); } template void RTLBMdynamicsMcHardyRK::computeEquilibriumAniso(Cell& cell, std::array& feq) { feq.fill( T() ); for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) { for ( int jPop = 0; jPop < DESCRIPTOR::q; ++jPop ) { feq[iPop] += cell[jPop] * _anisoMatrix[jPop][iPop]; } feq[iPop] *= descriptors::t(iPop); } } template std::array RTLBMdynamicsMcHardyRK::doCollision(Cell& cell, std::array& feq) { std::array k; for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { k[iPop] = - descriptors::norm_c(iPop)*(_absorption+_scattering) * (cell[iPop]) + descriptors::norm_c(iPop)*_scattering * feq[iPop]; } return k; } template void RTLBMdynamicsMcHardyRK::collide( Cell& cell, LatticeStatistics& statistics ) { std::array feq; std::array f_pre_collision; // separate cell and precollision f_i for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) { f_pre_collision[iPop] = cell[iPop] + descriptors::t(iPop); } // shift only first collision und equilibrium and then at the very end for ( int iPop = 0; iPop < DESCRIPTOR::q; ++iPop ) { cell[iPop] += descriptors::t(iPop); } computeEquilibriumAniso(cell,feq); std::array k1 = doCollision(cell,feq); // update cell for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = f_pre_collision[iPop] + 0.5*k1[iPop]; } computeEquilibriumAniso(cell,feq); std::array k2 = doCollision(cell,feq); // update cell for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = f_pre_collision[iPop] + 0.5*k2[iPop]; } computeEquilibriumAniso(cell,feq); std::array k3 = doCollision(cell,feq); // update cell for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = f_pre_collision[iPop] + k3[iPop]; } computeEquilibriumAniso(cell,feq); std::array k4 = doCollision(cell,feq); // update cell for (int iPop = 0; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] = f_pre_collision[iPop] + 1/6.*(k1[iPop] + 2*k2[iPop] + 2*k3[iPop] + k4[iPop]) - descriptors::t(iPop); // back shift for OpenLB } T temperature = lbHelpers::computeRho(cell); statistics.incrementStats( temperature, T() ); } template T RTLBMdynamicsMcHardyRK::getOmega() const { return -1; } template void RTLBMdynamicsMcHardyRK::setOmega( T omega ) { } } // namespace olb #endif