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