/* This file is part of the OpenLB library * * Copyright (C) 2018 Robin Trunk, Sam Avis * OpenLB 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 FREE_ENERGY_DYNAMICS_HH #define FREE_ENERGY_DYNAMICS_HH #include "core/cell.h" #include "dynamics/firstOrderLbHelpers.h" #include "dynamics/freeEnergyDynamics.h" namespace olb { template FreeEnergyBGKdynamics::FreeEnergyBGKdynamics ( T omega_, T gamma_, Momenta& momenta ) : BasicDynamics(momenta), omega(omega_), gamma(gamma_) { } template void FreeEnergyBGKdynamics::collide ( Cell& cell, LatticeStatistics& statistics ) { T rho, u[DESCRIPTOR::d]; for(int iDim=0; iDim()[iDim]; } rho = this->_momenta.computeRho(cell); T uSqr = lbHelpers::bgkCollision(cell, rho, u, omega); statistics.incrementStats(rho, uSqr); T tmp = gamma * descriptors::invCs2() * cell.template getFieldPointer()[0]; for(int iPop=1; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] -= omega * descriptors::t(iPop) * (rho - tmp); } cell[0] += omega * (1.-descriptors::t(0)) * (rho - tmp); } template T FreeEnergyBGKdynamics::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T ) const { T uSqr = 0.; T equilibrium = lbHelpers::equilibrium(iPop, rho, u, uSqr); T tmp = 0; //gamma * descriptors::invCs2() * cell.template getFieldPointer()[0]; if (iPop == 0) { equilibrium += (1.-descriptors::t(0)) * (rho - tmp); } else { equilibrium -= descriptors::t(iPop) * (rho - tmp); } return equilibrium; } template T FreeEnergyBGKdynamics::getOmega() const { return omega; } template void FreeEnergyBGKdynamics::setOmega(T omega_) { omega = omega_; } template void FreeEnergyBGKdynamics::computeRhoU ( Cell const& cell, T& rho, T u[DESCRIPTOR::d]) const { rho = this->_momenta.computeRho(cell); computeU(cell, u); } template void FreeEnergyBGKdynamics::computeU ( Cell const& cell, T u[DESCRIPTOR::d]) const { for (int iVel=0; iVel()[iVel]; } } /////////////// FreeEnergyWallDynamics //////////////////////////////////////// template FreeEnergyWallDynamics::FreeEnergyWallDynamics () : BounceBack () { } template T FreeEnergyWallDynamics::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { T equilibrium = lbHelpers::equilibrium(iPop, rho, u, uSqr); if (iPop == 0) { equilibrium += (1.-descriptors::t(0)) * rho; } else { equilibrium -= descriptors::t(iPop) * rho; } return equilibrium; } template T FreeEnergyWallDynamics::getOmega() const { return 0.; } template void FreeEnergyWallDynamics::setOmega(T omega_) { } /////////////// FreeEnergyInletOutletDynamics //////////////////////////////////////// template FreeEnergyInletOutletDynamics::FreeEnergyInletOutletDynamics ( T omega_, Momenta& momenta ) : BasicDynamics(momenta), omega(omega_) { } template void FreeEnergyInletOutletDynamics::collide ( Cell& cell, LatticeStatistics& statistics ) { typedef DESCRIPTOR L; // Do a standard collision neglecting the chemical potential term. T rho, u[DESCRIPTOR::d]; computeRhoU(cell, rho, u); T uSqr = lbHelpers::bgkCollision(cell, rho, u, omega); statistics.incrementStats(rho, uSqr); for(int iPop=1; iPop < DESCRIPTOR::q; ++iPop) { cell[iPop] -= omega * descriptors::t(iPop) * rho; } cell[0] += omega * (1.-descriptors::t(0)) * rho; // Distribute the missing density to the unknown distribution functions. std::vector missingIndices = util::subIndexOutgoing(); T missingRho = rho - 1.; T missingWeightSum = 0; for (int iPop = 0; iPop < L::q; ++iPop) { if ( std::find(missingIndices.begin(), missingIndices.end(), iPop) != missingIndices.end() ) { missingWeightSum += descriptors::t(iPop); } else { missingRho -= cell[iPop]; } } for (unsigned iPop = 0; iPop < missingIndices.size(); ++iPop) { cell[missingIndices[iPop]] = missingRho * descriptors::t(missingIndices[iPop]) / missingWeightSum; } } template T FreeEnergyInletOutletDynamics::computeEquilibrium( int iPop, T rho, const T u[DESCRIPTOR::d], T uSqr) const { T equilibrium = lbHelpers::equilibrium(iPop, rho, u, uSqr); if (iPop == 0) { equilibrium += (1.-descriptors::t(0)) * rho; } else { equilibrium -= descriptors::t(iPop) * rho; } return equilibrium; } template T FreeEnergyInletOutletDynamics::getOmega() const { return omega; } template void FreeEnergyInletOutletDynamics::setOmega(T omega_) { omega = omega_; } template T FreeEnergyInletOutletDynamics::computeRho( Cell const& cell) const { return cell.template getField()[0]; } template void FreeEnergyInletOutletDynamics::computeU ( Cell const& cell, T u[DESCRIPTOR::d]) const { for (int iVel=0; iVel()[1]; } template void FreeEnergyInletOutletDynamics::computeRhoU ( Cell const& cell, T& rho, T u[DESCRIPTOR::d]) const { rho = computeRho(cell); computeU(cell, u); } template void FreeEnergyInletOutletDynamics::defineRho( Cell& cell, T rho) { cell.template getFieldPointer()[0] = rho; } template void FreeEnergyInletOutletDynamics::defineU( Cell& cell, const T u[DESCRIPTOR::d]) { cell.template getFieldPointer()[1] = u[direction]; } } #endif