LBIBCell
 All Classes Functions Variables Friends Pages
DiracD2Q5.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/nodes/BoundaryNode.hpp>
23 #include <LbmLib/include/nodes/PhysicalNode.hpp>
24 #include <LbmLib/include/GlobalSimulationParameters.hpp>
25 #include <LbmLib/include/solver/BoundaryAbstractSolver.hpp>
26 #include <LbmLib/include/solver/CDESolver/DiracD2Q5.hpp>
27 #include <LbmLib/include/Constants.hpp>
28 
29 #include <UtilLib/include/Exception.hpp>
30 #include <UtilLib/include/Log.hpp>
31 #include <algorithm>
32 #include <cassert>
33 #include <numeric>
34 #include <string>
35 #include <random>
36 
37 namespace LbmLib {
38 namespace solver {
39 namespace {
40 const double pos = 32;
41 constexpr double D = 0.04;
42 
47 double deltaDiracStart(double deltaX) {
48  constexpr double t = 50;
49  return std::exp(-deltaX * deltaX / (4.0 * D * t)) / (4.0 * PI * D * t);
50 }
51 }
52 
54  double dist =
55  std::sqrt((pos -
57  (pos -
59  (pos -
60  physicalNode_->getYPos()) * (pos - physicalNode_->getYPos()));
61  for (auto d : cdeDirIter_) {
62  distributions_[d] = deltaDiracStart(dist) * 0.2;
63  }
64 
65  collide();
66 }
67 
68 void DiracD2Q5::writeSolver(std::ostream* const stream) {
69  (*stream) << physicalNode_->getXPos() << '\t' << physicalNode_->getYPos();
70  for (auto d : distributions_) {
71  (*stream) << '\t' << d;
72  }
73  (*stream) << '\n';
74 }
75 
76 void DiracD2Q5::loadSolver(std::stringstream* const stream) {
77  int x, y;
78  (*stream) >> x >> y;
79  assert(physicalNode_->getXPos() == x && "The position does not match");
80  assert(physicalNode_->getYPos() == y && "The position does not match");
81  for (auto d : cdeDirIter_) {
82  (*stream) >> distributions_[d];
83  }
84 }
85 
86 double& DiracD2Q5::accessDistribution(const Direction& dir) {
87  assert(dir > T && dir < NE);
88  return distributions_[dir];
89 }
90 
91 void DiracD2Q5::rescaleDistributions(const double factor) {
92  for (auto &it: this->distributions_) {
93  it *= factor;
94  }
95 }
96 
97 double DiracD2Q5::getC() const {
98  return std::accumulate(distributions_.begin(), distributions_.end(), 0.0);
99 }
100 
102  assert(physicalNode_ != nullptr);
103  assert(distributions_[0] == 0.0);
104  // Calculate the rho
105  const double C = getC();
106 
107  // calculate the speeds
108  const double ux = physicalNode_->getFluidSolver().getVelocity().x;
109  const double uy = physicalNode_->getFluidSolver().getVelocity().y;
110  // std::cout<<std::sqrt(ux*ux+uy*uy)<<std::endl;
111  const double w0 = C / 3.0;
112  const double w1 = C / 6.0;
113  const double tauI = 1.0 / getTau();
114 
115 
116  double temp[5];
117  temp[T] = w0;
118  temp[E] = w1 * (1.0 + ux * 3.0);
119  temp[N] = w1 * (1.0 + uy * 3.0);
120  temp[W] = w1 * (1.0 + (-ux) * 3.0);
121  temp[S] = w1 * (1.0 + (-uy) * 3.0);
122 
123  for (auto d : cdeDirIter_) {
124  double tempD = distributions_[d];
125  // compute non equilibirum
126  // make relaxation
127  distributions_[d] = tempD - tempD * tauI + temp[d] * tauI;
128  }
129 
130 
131  // preparation for advect step
132  localSwap();
133 }
134 
135 double DiracD2Q5::calculateEquilibrium(const Direction& dir) {
136  const double C = getC();
137  // calculate the speeds
138  const double u = physicalNode_->getFluidSolver().getVelocity().x;
139  const double v = physicalNode_->getFluidSolver().getVelocity().y;
140 
141  const double w1 = C / 6.0;
142 
143  switch (dir) {
144  case T:
145  return C / 3.0;
146  break;
147  case E:
148  return w1 * (1.0 + u * 3.0);
149  break;
150  case N:
151  return w1 * (1.0 + v * 3.0);
152  break;
153  case W:
154  return w1 * (1.0 + (-u) * 3.0);
155  break;
156  case S:
157  return w1 * (1.0 + (-v) * 3.0);
158  break;
159  default:
160  assert(
161  false &&
162  "you want to get a inverse direction of a Direction that does not exist");
163  }
164  return 0;
165 }
166 
168  assert(physicalNode_ != nullptr);
169  if (physicalNode_->getBoundaryNeighbour(W) == nullptr) {
170  std::swap(distributions_[getInverseDirection(
171  W)],
174  }
175  if (physicalNode_->getBoundaryNeighbour(S) == nullptr) {
176  std::swap(distributions_[getInverseDirection(
177  S)],
180  }
181 }
182 
183 void DiracD2Q5::localSwap() {
184  std::swap(distributions_[E], distributions_[W]);
185  std::swap(distributions_[N], distributions_[S]);
186 }
187 
189  double sumC = 0.0;
190  int counter = 0;
191  for (auto d : cdeDirIter_) {
192  // if it has no boundary neighbour and the neighbour is in the same domain then get the concentration
193  if (d != T && (this->physicalNode_->getBoundaryNeighbour(d) == nullptr) &&
196  getDomainIdentifier()) ) {
198  solverID_).getC();
199  counter++;
200  }
201  }
202  if (counter == 0) {
203  std::array<Direction, 4> dir {{NE, NW, SW, SE}
204  };
205  for (auto d : dir) {
206  // we need to check the diagonals as it does not work in the other directions
207  if (this->physicalNode_->getDomainIdentifier() ==
209  getDomainIdentifier()) {
210  sumC +=
212  solverID_).getC();
213  counter++;
214  }
215  }
216  LOG(UtilLib::logINFO) <<
217  "the default initialisation failed. Therefore the node was reinitialised from the diagonal directions";
218  }
219  if (counter == 0) {
221  "The cde solver failed to reinitialise the node, this might be due to a stange geometry");
222  }
223  sumC /= static_cast<double>(counter);
224  for (auto d : cdeDirIter_) {
225  distributions_[d] = sumC / 4.0;
226  }
227  this->collide();
228 }
229 
230 const std::string DiracD2Q5::name = "DiracD2Q5";
231 
232 
233 CDEDirectionsIteratorD2Q5 const DiracD2Q5::cdeDirIter_ =
235 
236 DiracD2Q5::DiracD2Q5() : BaseCDESolver(),
237  distributions_(std::array<double,
238  5> {
239  {0.0, 0.0, 0.0,
240  0.0, 0.0}
241  }
242 
243  )
244 {}
245 }
246 } // end namespace
virtual void advect()
advect The advect step of the LBM
Definition: DiracD2Q5.cpp:167
virtual double calculateEquilibrium(const Direction &dir)
calculateEquilibrium calculates the equilibirum for direction dir
Definition: DiracD2Q5.cpp:135
virtual void reinitialise()
reinitialise this solver as the corresponding physical node has switched domain
Definition: DiracD2Q5.cpp:188
virtual void initSolver()
initSolver Use this to initalise the solver
Definition: DiracD2Q5.cpp:53
virtual void rescaleDistributions(const double factor)
Rescales all distributions by a factor.
Definition: DiracD2Q5.cpp:91
The Base class for all CDESolver implementations This classes uses the recursive template idiom to au...
virtual void writeSolver(std::ostream *const stream)
writes the solver to the stream
Definition: DiracD2Q5.cpp:68
size_t solverID_
solverID_ The ID of the solver instance. Coincides with the index in the vector PhysicalNode::cdeSolv...
PhysicalNode * getPhysicalNeighbour(const Direction &d) const
getPhysicalNeighbour Getter method to access the Physical Neighbour
const nodes::PhysicalNode * physicalNode_
physicalNode_ The physical Node which owns this solver
The CDEDirectionsIteratorD2Q5 class Provides methods to handle the Directions. Use the Function Direc...
Definition: Direction.hpp:126
T x
x the value in x direction
Definition: Field.hpp:50
virtual double & accessDistribution(const Direction &dir)=0
accessDistribution Access to the distribution
unsigned int getDomainIdentifier() const
getter for the Domain Identifier of this node
virtual double & accessDistribution(const Direction &dir)
accessDistribution Access to the distribution
Definition: DiracD2Q5.cpp:86
virtual double getC() const =0
getC Calculates the concentration on this node
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 collide()
collide The collision step of the LBM
Definition: DiracD2Q5.cpp:101
BoundaryNode * getBoundaryNeighbour(const Direction &d) const
getBoundaryNeighbour Getter method to access the Boundary Neighbour
virtual double getC() const
getC Calculates the concentration on this node
Definition: DiracD2Q5.cpp:97
int getYPos() const
getYPos Getter for the Y position
virtual void loadSolver(std::stringstream *const stream)
loads the solver from the stream
Definition: DiracD2Q5.cpp:76
solver::CDEAbstractSolver & getCDESolver(size_t id) const
getCDESolver Getter method for the cde Solver
T y
y the value in y direction
Definition: Field.hpp:54