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