LBIBCell
 All Classes Functions Variables Friends Pages
GeometryNode.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/GeometryNode.hpp>
23 #include <LbmLib/include/nodes/PhysicalNode.hpp>
24 #include <UtilLib/include/geometry/Rectangle.hpp>
25 #include <LbmLib/include/Constants.hpp>
26 #include <UtilLib/include/Log.hpp>
27 #include <LbmLib/include/Field.hpp>
28 #include <string>
29 #include <random>
30 #include <iostream>
31 #include <iomanip>
32 #include <limits>
33 #include <cmath>
34 #include <cassert>
35 #include <omp.h>
36 
37 namespace LbmLib {
38 namespace geometry {
39 class Connection;
40 }
41 }
42 
43 namespace LbmLib {
44 namespace nodes {
45 namespace {
46 
47 constexpr double halfPi = M_PI / 2.0;
48 constexpr double doublePi = 2.0 * M_PI;
49 
55 inline double fastCos(const double x) {
56  //compute cosine: sin(x + PI/2) = cos(x)
57  double cos;
58  double tempx = x + halfPi;
59  if (tempx > M_PI) {
60  tempx -= doublePi;
61  }
62  if (tempx < .00) {
63  cos = 1.27323954 * tempx + 0.405284735 * tempx * tempx;
64  if (cos < 0.0) {
65  cos = 0.225 * (cos *-cos - cos) + cos;
66  }
67  else {
68  cos = 0.225 * (cos * cos - cos) + cos;
69  }
70  }
71  else {
72  cos = 1.27323954 * tempx - 0.405284735 * tempx * tempx;
73  if (cos < 0.0) {
74  cos = 0.225 * (cos *-cos - cos) + cos;
75  }
76  else {
77  cos = 0.225 * (cos * cos - cos) + cos;
78  }
79  }
80 return cos;
81 }
82 
89 inline double calculateDiscreteDeltaDirac(const double xpos,const double ypos) {
90  return (
91  (1.0 + fastCos(halfPi * xpos)) *
92  (1.0 + fastCos(halfPi * ypos))
93  ) / 16.0;
94 }
95 }
96 
97 // hack to make sure that the connections works. difference between oldPos to new must be greater than 1
99  double x,
100  double y,
101  unsigned int id) : LagrangianPoint(x, y),
102  oldPosition_(x - 5.0, y - 5.0),
103  id_(id),
104  neighbourPhysicalNodes_(std::array<PhysicalNode*,
105  16> {{nullptr, nullptr, nullptr,
106  nullptr, nullptr, nullptr,
107  nullptr, nullptr, nullptr,
108  nullptr, nullptr, nullptr,
109  nullptr, nullptr, nullptr,
110  nullptr}}),
111  connections_(std::array<std::shared_ptr<LbmLib::geometry::Connection>,
112  2> {{nullptr,
113  nullptr}})
114 
115 {
116  perturbatePosition();
117 }
118 
120 {
121  std::stringstream message;
122  message << "GeometryNode with nodeid=" << this->getId() << " finally destroyed.";
123  LOG(UtilLib::logDEBUG1) << message.str().c_str();
124 }
125 
126 void GeometryNode::writeNode(std::ostream* stream) {
127  (*stream) << id_ << '\t' << getXPos() << '\t' << getYPos() << '\n';
128 }
129 
131  force_ += f;
132 }
133 
135  PhysicalNode* const physicalNode,
136  unsigned int pos) {
137  assert(pos < 16);
138  assert(physicalNode != nullptr);
139  neighbourPhysicalNodes_[pos] = physicalNode;
140  assert(physicalNode == neighbourPhysicalNodes_[pos]);
141 }
142 
144  double x,
145  double y) {
146 #pragma omp critical
147  {
149  perturbatePosition();
150  }
151 }
152 
153 void GeometryNode::perturbatePosition() {
154  const int seed = 1; // for debugging
155  static std::random_device rd;
156  //static std::mt19937 gen(rd());
157  static std::mt19937 gen(seed);
158  static std::uniform_real_distribution<> dis(-PERTURBATION, PERTURBATION);
159  double temprand;
160  if (std::abs(static_cast<int>(getXPos()) - getXPos()) <= EPSILON) {
161  std::stringstream message;
162  message << std::setprecision(12)
163  << "Perturbation of GeometryNode (ID="<<this->getId()<<") "
164  << "(" << this->getXPos() << "," << this->getYPos() << ")"
165  << "->";
166  temprand = 0.0;
167  while(std::abs(temprand) < 5.0*EPSILON) {
168  temprand = dis(gen);
169  }
170  LagrangianPoint::setPos(getXPos() + temprand, getYPos());
171  message << "(" << this->getXPos() << "," << this->getYPos() << ")";
172  LOG(UtilLib::logINFO) << message.str().c_str();
173  }
174  if (std::abs(static_cast<int>(getYPos()) - getYPos()) <= EPSILON) {
175  std::stringstream message;
176  message << std::setprecision(12)
177  << "Perturbation of GeometryNode (ID="<<this->getId()<<") "
178  << "(" << this->getXPos() << "," << this->getYPos() << ")"
179  << "->";
180  temprand = 0.0;
181  while(std::abs(temprand) < 5.0*EPSILON) {
182  temprand = dis(gen);
183  }
184  LagrangianPoint::setPos(getXPos(), getYPos() + temprand);
185  message << "(" << this->getXPos() << "," << this->getYPos() << ")";
186  LOG(UtilLib::logINFO) << message.str().c_str();
187  }
188 
189  if (std::abs(getYPos() - std::floor(getYPos()) -
190  (getXPos() - std::floor(getXPos()))) <= EPSILON) {
191  std::stringstream message;
192  message << std::setprecision(12);
193  message << "Perturbation of GeometryNode (ID="<<this->getId()<<") ";
194  message << "(" << this->getXPos() << "," << this->getYPos() << ")";
195  message << "->";
196  LagrangianPoint::setPos(getXPos() + dis(gen),
197  getYPos() + dis(gen));
198  message << "(" << this->getXPos() << "," << this->getYPos() << ")";
199  LOG(UtilLib::logINFO) << message.str().c_str();
200  }
201 
202  if (std::abs(std::ceil(getYPos()) - getYPos() -
203  (getXPos() - std::floor(getXPos()))) <= EPSILON) {
204  std::stringstream message;
205  message << std::setprecision(12);
206  message << "Perturbation of GeometryNode (ID="<<this->getId()<<") ";
207  message << "(" << this->getXPos() << "," << this->getYPos() << ")";
208  message << "->";
209  LagrangianPoint::setPos(getXPos() + dis(gen),
210  getYPos() + dis(gen));
211  message << "(" << this->getXPos() << "," << this->getYPos() << ")";
212  LOG(UtilLib::logINFO) << message.str().c_str();
213  }
214 }
215 
217  Field<double> velocity;
218  for (const auto& node : neighbourPhysicalNodes_) {
219  Field<double> dist = getDistanceField(*this, *node);
220  velocity += calculateDiscreteDeltaDirac(dist.x,dist.y) *
221  node->getFluidSolver().getVelocity();
222  }
223  assert(std::isfinite(velocity.x));
224  assert(std::isfinite(velocity.y));
225  this->setVelocity(velocity);
226 }
227 
229  Field<double> dist;
230 #pragma omp parallel for schedule(dynamic) private(dist)
231  for (size_t it=0;it<this->neighbourPhysicalNodes_.size();++it) {
232  dist = nodes::getDistanceField(*this, *this->neighbourPhysicalNodes_[it]);
233  this->neighbourPhysicalNodes_[it]->getFluidSolver().addForce(calculateDiscreteDeltaDirac(dist.x,dist.y) * force_);
234  }
235 }
236 
238  force_ = f;
239 }
240 
241 std::string GeometryNode::getType() const {
242  return std::string("GeometryNode");
243 }
244 
246  this->oldPosition_.x = this->getXPos();
247  this->oldPosition_.y = this->getYPos();
248  // assume delta_time=1
249  assert(std::isfinite(this->getXPos()));
250  assert(std::isfinite(this->getYPos()));
251  assert(std::isfinite(this->getXVelocity()));
252  assert(std::isfinite(this->getYVelocity()));
254 }
255 
258  this->oldPosition_.y), std::floor(this->oldPosition_.y),
259  std::floor(this->oldPosition_.x), std::ceil(this->oldPosition_.x));
260  return !rec.pointWithinBounds(getXPos(), getYPos());
261 }
262 
263 unsigned int GeometryNode::getId() const {
264  return id_;
265 }
266 
268 {
269  unsigned int temp;
270  assert(this->getConnection<0>() != nullptr);
271  assert(this->getConnection<1>() != nullptr);
272 
273  temp = this->getConnection<0>()->getDomainIdentifier();
274  if (this->getConnection<1>()->getDomainIdentifier() != temp) {
275  std::stringstream message;
276  message << std::setprecision(12) <<
277  "GeometryNode ID="<<this->getId()<<") " <<
278  "(" << this->getXPos() << "," << this->getYPos() << ")" <<
279  " has adjacent connections with non-identical domainIdentifiers";
280  LOG(UtilLib::logINFO) << message.str().c_str();
281  }
282  return temp;
283 }
284 
285 }
286 } // end namespace
virtual void setVelocity(Field< double > velocity)
setVelocity Set the velocity
void addPhysicalNode(PhysicalNode *const physicalNode, unsigned int pos)
addPhysicalNode Adds a physical node at a certain position
virtual std::string getType() const
getType The type of a node class
void setForce(Field< double > f)
set the force of this node
unsigned int getDomainIdOfAdjacentConnections(void) const
get the domainID of the (max two) adjacent *Connection*s
double getYPos() const
getYPos Getter for the Y position
class representing a physical node
T x
x the value in x direction
Definition: Field.hpp:50
void collectVelocity()
collectVelocity collects the velocities from the fluid nodes to the geometry Nodes ...
bool pointWithinBounds(double x, double y) const
pointWithinBounds Checks if point is contained inside this rectangle
Definition: Rectangle.cpp:63
void distributeForce()
distributes the Force to the fluid nodes
bool isUpdateNeeded() const
isUpdateNeeded Calculates if the connections of this points need to be updates
void move()
movePoint Moves the geomety node exactly one timestep
double getXPos() const
getXPos Getter for the X position
double getXVelocity() const
getXVelocity Getter for x-velocity component
unsigned int getId() const
getter for the node id
virtual void setPos(double x, double y)
setPos Set the position new override to make sure that perturbation occures
~GeometryNode()
~GeometryNode Destructor
void writeNode(std::ostream *stream)
writes the node to the stream
GeometryNode(double x, double y, unsigned int id)
GeometryNode constructs a Geometry node.
double getYVelocity() const
getYVelocity Getter for the y-velocity component
T y
y the value in y direction
Definition: Field.hpp:54
void addForce(Field< double > f)
adds the force to the force of this node
The LagrangianPoint class A class for storing a point's coordinates and its velocity This class is th...
a class representing a rectangle
Definition: Rectangle.hpp:30
virtual void setPos(double x, double y)
setPos Set the position new override this method to change default behaviour