LBIBCell
 All Classes Functions Variables Friends Pages
FluidSolver.cpp
1 /* Copyright (c) 2013 David Sichau <mail"at"sichau"dot"eu>
2  * 2013-2015 Simon Tanaka <tanakas"at"gmx"dot"ch>
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20  * THE SOFTWARE.
21  */
22 #include <LbmLib/include/Constants.hpp>
23 #include <LbmLib/include/GlobalSimulationParameters.hpp>
24 #include <LbmLib/include/nodes/PhysicalNode.hpp>
25 #include <LbmLib/include/solver/FluidSolver/FluidSolver.hpp>
26 #include <LbmLib/include/solver/FluidSolver/FluidSolver.hpp>
27 #include <UtilLib/include/Log.hpp>
28 #include <algorithm>
29 #include <cassert>
30 #include <numeric>
31 #include <sstream>
32 #include <string>
33 namespace LbmLib {
34 namespace solver {
35 namespace {
39 constexpr double W0 = 4.0 / 9.0;
43 constexpr double W1 = 1.0 / 9.0;
47 constexpr double W2 = 1.0 / 36.0;
48 }
49 
51  if (velocityInit_) {
52  initWithVelocity();
53  } else {
54  // init the populations with rho = 1 and u=0 and v=0
55  // hack to set rho to 1 for the init step
56 
57  distributions_[T] = 1.0;
58  collide();
59  }
60 }
61 
62 void FluidSolver::initWithVelocity() {
63  const double rho = 1.0;
64 
65  // calculate the speeds
66  const double u = velocity_.x;
67  const double v = velocity_.y;
68 
69  const double u2 = u * u;
70  const double v2 = v * v;
71 
72  const double W1rho = W1 * rho;
73  const double W2rho = W2 * rho;
74  const double W3 = 9.0 / 2.0;
75  const double lastTerm = 3.0 / 2.0 * (u2 + v2);
76 
77  double temp[9];
78 
79  temp[T] = W0 * rho * (1.0 - lastTerm);
80  temp[E] = W1rho * (1.0 + 3.0 * u + W3 * u2 - lastTerm);
81  temp[NE] = W2rho * (1.0 + 3.0 * (u + v) + W3 * (u + v) * (u + v) - lastTerm);
82  temp[N] = W1rho * (1.0 + 3.0 * v + W3 * v2 - lastTerm);
83  temp[NW] = W2rho *
84  (1.0 + 3.0 * (-u + v) + W3 * (-u + v) * (-u + v) - lastTerm);
85  temp[W] = W1rho * (1.0 + 3.0 * (-u) + W3 * u2 - lastTerm);
86  temp[SW] = W2rho *
87  (1.0 + 3.0 * (-u - v) + W3 * (-u - v) * (-u - v) - lastTerm);
88  temp[S] = W1rho * (1.0 + 3.0 * (-v) + W3 * v2 - lastTerm);
89  temp[SE] = W2rho * (1.0 + 3.0 * (u - v) + W3 * (u - v) * (u - v) - lastTerm);
90 
91  for (auto d : dirIter_) {
92  // assign the equilibirum to the distribution
93  // make relaxation
94  distributions_[d] = temp[d];
95  }
96 
97 
98  // reseting the rho to add to zero as it is shifted to the distributions
99  rhoToAdd_ = 0.0;
100  localSwap();
101 }
102 
104 
105  // Calculate the rho
106  double rho = this->getRho();
107  assert(rho>0.0);
108  if (std::isfinite(this->rhoToAdd_)) {
109  rho += this->rhoToAdd_;
110  }
111  if (rho>0.0) {
112 
113  }
114  else {
115  std::cout<<"rhoToAdd="<<this->rhoToAdd_<<std::endl;
116  }
117  assert(rho>0.0);
118  double rhoI = 1.0 / rho;
119  assert(std::isfinite(rhoI));
120 
121  // calculate the velocity
122  Field<double> u;
123  computeVelocity(rho,this->distributions_,this->force_,u);
124  const double ux2 = u.x * u.x;
125  const double uy2 = u.y * u.y;
126 
127 
128  const double lastTerm = 3.0 / 2.0 * (ux2 + uy2);
129  const double tauI = 1.0 / getTau();
130 
131  double temp[9];
132 
133  const double W3 = 9.0 / 2.0;
134  const double W1rho = W1 * rho;
135  const double W2rho = W2 * rho;
136 
137  // the force calculation is added to the temp calculation
138  // an if condition to check if the force is zero is the same speed as simply calculate this
139  // A.A. Mohamad, A. Kuzmin (2010): A critical evaluation of force term in lattice Boltzmann method, natural convection problem
140  std::vector<double> forcecontribution;
141  this->computeForce(this->getTau(),
142  this->getRho(),
143  this->getVelocity(),
144  this->force_,
145  forcecontribution);
146 
147  temp[T] = W0 * rho * (1.0 - lastTerm) * tauI +
148  forcecontribution[T];
149  temp[E] = W1rho * (1.0 + 3.0 * u.x + W3 * ux2 - lastTerm) * tauI +
150  forcecontribution[E];
151  temp[NE] = W2rho * (1.0 + 3.0 * (u.x + u.y) + W3 * (u.x + u.y) * (u.x + u.y) - lastTerm) * tauI +
152  forcecontribution[NE];
153  temp[N] = W1rho * (1.0 + 3.0 * u.y + W3 * uy2 - lastTerm) * tauI +
154  forcecontribution[N];
155  temp[NW] = W2rho * (1.0 + 3.0 * (-u.x + u.y) + W3 * (-u.x + u.y) * (-u.x + u.y) - lastTerm) * tauI +
156  forcecontribution[NW];
157  temp[W] = W1rho * (1.0 + 3.0 * (-u.x) + W3 * ux2 - lastTerm) * tauI +
158  forcecontribution[W];
159  temp[SW] = W2rho * (1.0 + 3.0 * (-u.x - u.y) + W3 * (-u.x - u.y) * (-u.x - u.y) - lastTerm) * tauI +
160  forcecontribution[SW];
161  temp[S] = W1rho * (1.0 + 3.0 * (-u.y) + W3 * uy2 - lastTerm) * tauI +
162  forcecontribution[S];
163  temp[SE] = W2rho * (1.0 + 3.0 * (u.x - u.y) + W3 * (u.x - u.y) * (u.x - u.y) - lastTerm) * tauI +
164  forcecontribution[SE];
165 
166  for (auto d : dirIter_) {
167  const double tempD = distributions_[d];
168  // compute non equilibirum and make relaxation
169  distributions_[d] = tempD - tempD * tauI + temp[d];
170  }
171 
172  // recalculate the velocity
173  computeVelocity(rho,this->distributions_,this->force_,u);
174  assert(std::isfinite(u.x));
175  assert(std::isfinite(u.y));
176  velocity_.x = u.x;
177  velocity_.y = u.y;
178 
179  // reseting the rho to add to zero as it is shifted to the distributions
180  rhoToAdd_ = 0.0;
181  // preparation for advect step
182  localSwap();
183 }
184 
186  std::swap(distributions_[E], physicalNode_.getPhysicalNeighbour(
188  std::swap(distributions_[NE], physicalNode_.getPhysicalNeighbour(
190  std::swap(distributions_[N], physicalNode_.getPhysicalNeighbour(
192  std::swap(distributions_[NW], physicalNode_.getPhysicalNeighbour(
194 }
195 
197  force_ += f;
198 }
199 
200 void FluidSolver::writeSolver(std::ostream* const stream) {
201  (*stream) << physicalNode_.getXPos() << '\t' << physicalNode_.getYPos();
202  for (auto d : distributions_) {
203  (*stream) << '\t' << d;
204  }
205  (*stream) << '\n';
206 }
207 
208 void FluidSolver::loadSolver(std::stringstream* const stream) {
209  int x, y;
210  // reset of the stringstream
211  stream->seekg(0);
212  (*stream) >> x >> y;
213  assert(physicalNode_.getXPos() == x && "The position does not match");
214  assert(physicalNode_.getYPos() == y && "The position does not match");
215  for (auto d : dirIter_) {
216  (*stream) >> distributions_[d];
217  }
218 }
219 
221  force_.x = 0.0;
222  force_.y = 0.0;
223 }
224 
225 double& FluidSolver::accessDistribution(const Direction& dir) {
226  return distributions_[dir];
227 }
228 
229 void FluidSolver::rescaleDistributions(const double factor) {
230  for (auto &it: this->distributions_) {
231  it *= factor;
232  }
233 }
234 
236  velocity_ = velocity;
237  assert(std::isfinite(this->velocity_.x));
238  assert(std::isfinite(this->velocity_.y));
239  velocityInit_ = true;
240 }
241 
243  assert(std::isfinite(this->velocity_.x));
244  assert(std::isfinite(this->velocity_.y));
245  return velocity_;
246 }
247 
248 double FluidSolver::getRho() const {
249  return std::accumulate(distributions_.begin(),
250  distributions_.end(), 0.0);
251 }
252 
253 void FluidSolver::addMass(double mass) {
254  this->rhoToAdd_ = 0.0;
255  this->rhoToAdd_ += mass;
256  LOG(UtilLib::logDEBUG4) << "mass added to the fluid. " << mass;
257 }
258 
259 void FluidSolver::localSwap() {
260  std::swap(distributions_[E], distributions_[W]);
261  std::swap(distributions_[NE], distributions_[SW]);
262  std::swap(distributions_[N], distributions_[S]);
263  std::swap(distributions_[NW], distributions_[SE]);
264 }
265 
267  : AbstractSolver(),
268  physicalNode_(physicalNode),
269  distributions_(std::array<double,
270  9> {{ 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }
271  }),
272  velocityInit_(false),
273  rhoToAdd_(0.0)
274 {}
275 
276 DirectionIterator const FluidSolver::dirIter_ = DirectionIterator();
277 }
278 } // end namespace
the base class of the cde and fluid solvers
void setVelocity(Field< double > velocity)
setVelocity Sets the velocity of this fluid Algorithm. Should only be used for initialisation.
void addForce(Field< double > f)
adds f to the current force
virtual void writeSolver(std::ostream *const stream)
writes the solver to the file
virtual void computeVelocity(const double rho, const std::array< double, 9 > &fi, const Field< double > f, Field< double > &u)
computeVelocity since this operation depends on the force model.
FluidSolver(const nodes::PhysicalNode &physicalNode)
FluidSolver Initialises the fluid solver.
virtual double & accessDistribution(const Direction &dir)
accessDistribution Access to the distribution
PhysicalNode * getPhysicalNeighbour(const Direction &d) const
getPhysicalNeighbour Getter method to access the Physical Neighbour
void addMass(double mass)
addMass The mass which is added to this fluid solver
class representing a physical node
T x
x the value in x direction
Definition: Field.hpp:50
virtual void initSolver()
initSolver Use this to initalise the solver
Definition: FluidSolver.cpp:50
double getRho() const
getRho Calculates the Rho
void resetForce()
resets the force on this fluid solver to 0
virtual void computeForce(const double tau, const double rho, const Field< double > u, const Field< double > f, std::vector< double > &forcecontribution)
computeForce
virtual void rescaleDistributions(const double factor)
Rescales all distributions by a factor.
const Field< double > & getVelocity() const
getVelocity Returns the current velocity of the fluid
double getTau() const
getTau Getter method for the tau parameter
const solver::FluidSolver & getFluidSolver() const
getFluidSolver Const getter method for the fluid Solver
int getXPos() const
getXPos Getter for the X position
virtual void loadSolver(std::stringstream *const stream)
loads the solver from the file
int getYPos() const
getYPos Getter for the Y position
virtual void advect()
advect The advect step of the LBM
virtual void collide()
collide The collision step of the LBM
T y
y the value in y direction
Definition: Field.hpp:54
The DirectionOperations_ class Provides methods to handle the Directions. Use the Function Directions...
Definition: Direction.hpp:57