/* This file is part of the OpenLB library * * Copyright (C) 2017 Albert Mink * 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. */ #ifndef RTLBM_BOUNDARY_DYNAMICS_HH #define RTLBM_BOUNDARY_DYNAMICS_HH #include "rtlbmBoundaryDynamics.h" #include "dynamics/lbHelpers.h" namespace olb { // flat diffuse template RtlbmDiffuseBoundaryDynamics::RtlbmDiffuseBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDiffuseBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return descriptors::t(iPop)*rho - descriptors::t(iPop); } template void RtlbmDiffuseBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { typedef DESCRIPTOR L; T dirichletTemperature = this->_momenta.computeRho(cell); std::vector const missing_iPop = util::subIndexOutgoing(); // compute summ of weights for all missing directions double sumWeights = 0; for ( int i : missing_iPop ) { sumWeights += descriptors::t(i); } // construct missing directions such that 0th moment equals emposed dirichletTemperature for ( int i : missing_iPop ) { cell[i] = descriptors::t(i)*dirichletTemperature/sumWeights - descriptors::t(i); } } template T RtlbmDiffuseBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDiffuseBoundaryDynamics::setOmega(T omega_) { } // edge diffuse template RtlbmDiffuseEdgeBoundaryDynamics::RtlbmDiffuseEdgeBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDiffuseEdgeBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return descriptors::t(iPop)*rho - descriptors::t(iPop); } template void RtlbmDiffuseEdgeBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { typedef DESCRIPTOR L; T dirichletTemperature = this->_momenta.computeRho(cell); std::vector missing_iPop = util::subIndexOutgoing3DonEdges(); // compute summ of weights for all missing directions double sumWeights = 0; for ( int i : missing_iPop ) { sumWeights += descriptors::t(i); } // construct missing directions such that 0th moment equals emposed dirichletTemperature for ( int i : missing_iPop ) { cell[i] = descriptors::t(i)*dirichletTemperature/sumWeights - descriptors::t(i); } } template T RtlbmDiffuseEdgeBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDiffuseEdgeBoundaryDynamics::setOmega(T omega_) { } // corner diffuse template RtlbmDiffuseCornerBoundaryDynamics::RtlbmDiffuseCornerBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDiffuseCornerBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return descriptors::t(iPop)*rho - descriptors::t(iPop); } template void RtlbmDiffuseCornerBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { typedef DESCRIPTOR L; T dirichletTemperature = this->_momenta.computeRho(cell); std::vector const missing_iPop = util::subIndexOutgoing3DonCorners(); // compute summ of weights for all missing directions double sumWeights = 0; for ( int i : missing_iPop ) { sumWeights += descriptors::t(i); } // construct missing directions such that 0th moment equals emposed dirichletTemperature for ( int i : missing_iPop ) { cell[i] = descriptors::t(i)*dirichletTemperature/sumWeights - descriptors::t(i); } } template T RtlbmDiffuseCornerBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDiffuseCornerBoundaryDynamics::setOmega(T omega_) { } // flat diffuse constant density template RtlbmDiffuseConstBoundaryDynamics::RtlbmDiffuseConstBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDiffuseConstBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return descriptors::t(iPop)*rho - descriptors::t(iPop); } template void RtlbmDiffuseConstBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { // For direction i \in I_in define // cell_i = w_i * dirichlet/sumWeights - w_i // For direction i \in I_out defube // cell_i = - w_i // This construction yields // sum_{i=0}^{q-1} cell_i == dirichlet - 1 typedef DESCRIPTOR L; // shift all: cell_i = f_i - weight_i for ( int iPop = 0; iPop < L::q; ++iPop ) { cell[iPop] = - descriptors::t(iPop); } std::vector const missing_iPop = util::subIndexOutgoing(); // compute summ of weights for all missing directions double sumWeights = 0; for ( int i : missing_iPop ) { sumWeights += descriptors::t(i); } // construct missing directions such that 0th moment equals emposed dirichletTemperature T dirichletTemperature = this->_momenta.computeRho(cell); for ( int i : missing_iPop ) { cell[i] = descriptors::t(i)*dirichletTemperature/sumWeights - descriptors::t(i); } } template T RtlbmDiffuseConstBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDiffuseConstBoundaryDynamics::setOmega(T omega_) { } // edge diffuse with constant density template RtlbmDiffuseConstEdgeBoundaryDynamics::RtlbmDiffuseConstEdgeBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDiffuseConstEdgeBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return descriptors::t(iPop)*rho - descriptors::t(iPop); } template void RtlbmDiffuseConstEdgeBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { // For direction i \in I_in define // cell_i = w_i * dirichlet/sumWeights - w_i // For direction i \in I_out defube // cell_i = - w_i // This construction yields // sum_{i=0}^{q-1} cell_i == dirichlet - 1 typedef DESCRIPTOR L; // shift all: cell_i = f_i - weight_i for ( int iPop = 0; iPop < L::q; ++iPop ) { cell[iPop] = - descriptors::t(iPop); } std::vector missing_iPop = util::subIndexOutgoing3DonEdges(); double sumWeights = 0; for ( int i : missing_iPop ) { sumWeights += descriptors::t(i); } T dirichletTemperature = this->_momenta.computeRho(cell); for ( int i : missing_iPop ) { cell[i] = descriptors::t(i)*dirichletTemperature/sumWeights - descriptors::t(i); } } template T RtlbmDiffuseConstEdgeBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDiffuseConstEdgeBoundaryDynamics::setOmega(T omega_) { } // corner diffuse with constant density template RtlbmDiffuseConstCornerBoundaryDynamics::RtlbmDiffuseConstCornerBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDiffuseConstCornerBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return descriptors::t(iPop)*rho - descriptors::t(iPop); } template void RtlbmDiffuseConstCornerBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { // For direction i \in I_in define // cell_i = w_i * dirichlet/sumWeights - w_i // For direction i \in I_out defube // cell_i = - w_i // This construction yields // sum_{i=0}^{q-1} cell_i == dirichlet - 1 typedef DESCRIPTOR L; // shift all: cell_i = f_i - weight_i for ( int iPop = 0; iPop < L::q; ++iPop ) { cell[iPop] = - descriptors::t(iPop); } std::vector const missing_iPop = util::subIndexOutgoing3DonCorners(); double sumWeights = 0; for ( int i : missing_iPop ) { sumWeights += descriptors::t(i); } T dirichletTemperature = this->_momenta.computeRho(cell); for ( int i : missing_iPop ) { cell[i] = descriptors::t(i)*dirichletTemperature/sumWeights - descriptors::t(i); } } template T RtlbmDiffuseConstCornerBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDiffuseConstCornerBoundaryDynamics::setOmega(T omega_) { } // directed wall template RtlbmDirectedBoundaryDynamics::RtlbmDirectedBoundaryDynamics( T omega_, Momenta& momenta_) : BasicDynamics(momenta_) { } template T RtlbmDirectedBoundaryDynamics::computeEquilibrium(int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { return lbHelpers::equilibriumFirstOrder( iPop, rho, u ); } template void RtlbmDirectedBoundaryDynamics::collide(Cell& cell,LatticeStatistics& statistics) { typedef DESCRIPTOR L; T dirichletTemperature = this->_momenta.computeRho(cell); for( int iPop = 0; iPop < L::q; ++iPop ) { cell[iPop] = - descriptors::t(iPop); } std::vector const missingDiagonal = util::subIndexOutgoing(); for ( int i : missingDiagonal ) { // compute norm of c_iPopMissing // is direction axis parallel if ( util::normSqr(descriptors::c(i)) == 1 ) { cell[i] = dirichletTemperature - descriptors::t(i); } } } template T RtlbmDirectedBoundaryDynamics::getOmega() const { return T(-1); } template void RtlbmDirectedBoundaryDynamics::setOmega(T omega_) { } } // namespace olb #endif