CentroidMotion.cpp
1 #include "CentroidMotion.hpp"
2 #include "../../../tessellation/ConvexHull.hpp"
3 #include "../../../misc/simple_io.hpp"
4 #include "../../../tessellation/VoronoiMesh.hpp"
5 #ifdef RICH_MPI
6 #include <mpi.h>
7 #include "../../../mpi/mpi_commands.hpp"
8 #endif
9 
10 namespace
11 {
12  void ConvexIndeces(vector<Vector2D> const& points,Vector2D const& meshpoint,vector<size_t> &convex_index)
13  {
14  // Start building the convexhull
15  size_t n = points.size();
16  vector<double> angles(n);
17  for (size_t i = 0; i<n; ++i)
18  angles.at(i) = atan2(points.at(i).y - meshpoint.y, points.at(i).x - meshpoint.x);
19  sort_index(angles, convex_index);
20  }
21 
22  void GetConvexPoints(vector<Vector2D> &chull,Vector2D meshpoint, double R,
23  vector<Vector2D> &res)
24  {
25  Edge e1, e2;
26  res.resize(chull.size());
27  bool retry = false;
28  for (size_t i = 0; i < res.size(); ++i)
29  {
30  Vector2D normal = chull[static_cast<size_t>(i)] - meshpoint;
31  normal = normal / abs(normal);
32  e1.vertices.first = 0.5*(chull[static_cast<size_t>(i)] + meshpoint);
33  e1.vertices.first += 500 * R*Vector2D(normal.y, -normal.x);
34  e1.vertices.second = e1.vertices.first - 1000 * R*Vector2D(normal.y, -normal.x);
35  normal = chull[static_cast<size_t>((i+1)%res.size())] - meshpoint;
36  normal = normal / abs(normal);
37  e2.vertices.first = 0.5*(chull[static_cast<size_t>((i + 1) % res.size())] + meshpoint);
38  e2.vertices.first += 500 * R*Vector2D(normal.y, -normal.x);
39  e2.vertices.second = e2.vertices.first - 1000 * R*Vector2D(normal.y, -normal.x);
40  if (!SegmentIntersection(e1, e2, res[i]))
41  {
42  if (!PointInCell(chull, meshpoint)&&!retry)
43  {
44  retry = true;
45  i = 0;
46  meshpoint.Set(0, 0);
47  for (size_t j = 0; j < res.size(); ++j)
48  meshpoint += chull[j];
49  meshpoint *= (1.0/static_cast<double>(res.size()));
50  vector<size_t> convex_indeces;
51  ConvexIndeces(chull, meshpoint, convex_indeces);
52  chull=VectorValues(chull, convex_indeces);
53  }
54  else
55  {
56  UniversalError eo("No intersection in centroid motion");
57 #ifdef RICH_MPI
58  int rank;
59  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
60  eo.AddEntry("Rank", rank);
61 #endif
62  eo.AddEntry("mesh.x", meshpoint.x);
63  eo.AddEntry("mesh.y", meshpoint.y);
64  eo.AddEntry("R", R);
65  for (size_t k = 0; k < chull.size(); ++k)
66  {
67  eo.AddEntry("chull x", chull[k].x);
68  eo.AddEntry("chull y", chull[k].y);
69  }
70  eo.AddEntry("e1.vertices.first.x", e1.vertices.first.x);
71  eo.AddEntry("e1.vertices.first.y", e1.vertices.first.y);
72  eo.AddEntry("e1.vertices.second.x", e1.vertices.second.x);
73  eo.AddEntry("e1.vertices.second.y", e1.vertices.second.y);
74  eo.AddEntry("e2.vertices.first.x", e2.vertices.first.x);
75  eo.AddEntry("e2.vertices.first.y", e2.vertices.first.y);
76  eo.AddEntry("e2.vertices.second.x", e2.vertices.second.x);
77  eo.AddEntry("e2.vertices.second.y", e2.vertices.second.y);
78  throw eo;
79  }
80  }
81  }
82  }
83 
84  Vector2D GetCM(vector<Vector2D> const& chull,Vector2D const& meshpoint)
85  {
86  double area = 0;
87  Vector2D res;
88  for (size_t i = 0; i < chull.size(); ++i)
89  {
90  const double area_temp = 0.5*std::abs(ScalarProd(chull[i]-meshpoint, zcross(chull[(i+1)%chull.size()]-meshpoint)));
91  area += area_temp;
92  res += (area_temp / 3.)*(meshpoint+chull[i]+ chull[(i + 1) % chull.size()]);
93  }
94  return res / area;
95  }
96 
97  void GetOrgChullPoints(Tessellation const& tess,vector<size_t> const& indeces, vector<Vector2D> &res)
98  {
99  res.resize(indeces.size());
100  for (size_t i = 0; i < indeces.size(); ++i)
101  res[i] = tess.GetMeshPoint(static_cast<int>(indeces[i]));
102  }
103 
104  void GetChullVelocity(Tessellation const & tess, vector<Vector2D> const& orgvel,
105  vector<size_t> const& indeces,
106 #ifdef RICH_MPI
107  int point
108 #else
109  int point
110 #endif
111  ,vector<Vector2D> &res)
112  {
113  res.resize(indeces.size());
114  const size_t N = static_cast<size_t>(tess.GetPointNo());
115  for (size_t i = 0; i < indeces.size(); ++i)
116  {
117  if(indeces[i]<N)
118  res[i] = orgvel[indeces[i]];
119  else
120  {
121  if (tess.GetOriginalIndex(static_cast<int>(indeces[i]) == static_cast<int>(indeces[i])))
122  {
123  Vector2D normal = tess.GetMeshPoint(point) - tess.GetMeshPoint(static_cast<int>(indeces[i]));
124  normal = normal / abs(normal);
125  Vector2D vel = orgvel[static_cast<size_t>(tess.GetOriginalIndex(static_cast<int>(indeces[i])))];
126  res[i] = vel - 2*normal*ScalarProd(vel,normal);
127  }
128  else
129 #ifdef RICH_MPI
130  res[i] = orgvel[indeces[i]];
131 #else
132  res[i] = orgvel[static_cast<size_t>(tess.GetOriginalIndex(static_cast<int>(indeces[i])))];
133 #endif
134  }
135  }
136  }
137 
138  Vector2D GetCorrectedVelociy(Vector2D const& cm,Vector2D const& meshpoint,Vector2D const& w,
139  double dt,double reduce_factor,double R,EquationOfState const& eos,ComputationalCell const& cell,TracerStickerNames
140  const &tsn)
141  {
142  Vector2D temp = cm - meshpoint - dt*w;
143  if(abs(temp)<1e-6*R)
144  return (cm - meshpoint) / dt;
145  const double distance_reduce = std::min(abs(temp) / R,1.0);
146  const double toadd_velocity = reduce_factor*distance_reduce * std::max(abs(w),
147  eos.dp2c(cell.density, cell.pressure,cell.tracers,tsn.tracer_names));
148  return (w + temp*(toadd_velocity / abs(temp)));
149  }
150 
151  bool ShouldCalc(vector<string> const& toignore, ComputationalCell const& cell,TracerStickerNames const&
152  tracerstickernames)
153  {
154  for (size_t i = 0; i < toignore.size(); ++i)
155  {
156  vector<string>::const_iterator it = binary_find(tracerstickernames.sticker_names.begin(),
157  tracerstickernames.sticker_names.end(), toignore[i]);
158  if (it != tracerstickernames.sticker_names.end() && cell.stickers[static_cast<size_t>(
159  it - tracerstickernames.sticker_names.begin())])
160  return false;
161  }
162  return true;
163  }
164 
165  vector<int> GetBoundaryEdges(Tessellation const& tess)
166  {
167  vector<int> res;
168  int N = tess.GetTotalSidesNumber();
169  for (int i = 0; i < N; ++i)
170  {
171  Edge const& edge = tess.GetEdge(i);
172  if (tess.GetOriginalIndex(edge.neighbors.first) == tess.GetOriginalIndex(edge.neighbors.second))
173  res.push_back(i);
174  }
175  return res;
176  }
177 
178  void SlowNearBoundary(vector<Vector2D> &res, vector<int> const&edges, Tessellation const& tess,double dt)
179  {
180  size_t N = edges.size();
181  int Npoints = tess.GetPointNo();
182  Vector2D n;
183  size_t vel_index;
184  for (size_t i = 0; i < N; ++i)
185  {
186  Edge const& edge = tess.GetEdge(edges[i]);
187  if (edge.neighbors.first < Npoints)
188  {
189  n = tess.GetMeshPoint(edge.neighbors.second) - tess.GetMeshPoint(edge.neighbors.first);
190  vel_index = static_cast<size_t>(edge.neighbors.first);
191  }
192  else
193  {
194  n = tess.GetMeshPoint(edge.neighbors.first) - tess.GetMeshPoint(edge.neighbors.second);
195  vel_index = static_cast<size_t>(edge.neighbors.second);
196  }
197  double l = abs(n);
198  double dx = ScalarProd(n, res[vel_index] * dt) / l;
199  if (dx > 0.5*l)
200  res[vel_index] += ((0.1*l- dx)/(dt*l))*n;
201  }
202  }
203 
204  vector<Vector2D> GetCorrectedVelocities(Tessellation const& tess,vector<Vector2D> const& w,double dt,
205  double reduce_factor,size_t Niter,vector<ComputationalCell> const& cells,EquationOfState const& eos,
206  vector<string> const& toignore, TracerStickerNames const& tracerstickernames)
207  {
208  size_t N = static_cast<size_t>(tess.GetPointNo());
209  vector<Vector2D> res(N);
210  vector<Vector2D> cur_w(w);
211  vector<size_t> convex_index;
212  vector<vector<size_t> > neighbor_indeces(N);
213  vector<Vector2D> chull,chull2,hull_vel;
214  for (size_t i = 0; i < N; ++i)
215  {
216  vector<int> neigh = tess.GetNeighbors(static_cast<int>(i));
217  for (size_t j = 0; j < neigh.size(); ++j)
218  neighbor_indeces[i].push_back(static_cast<size_t>(neigh[j]));
219  }
220  for (size_t j = 0; j < Niter; ++j)
221  {
222  for (size_t i = 0; i < N; ++i)
223  {
224  if (!ShouldCalc(toignore, cells[i],tracerstickernames))
225  continue;
226  GetOrgChullPoints(tess, neighbor_indeces[i],chull);
227  ConvexIndeces(chull, tess.GetMeshPoint(static_cast<int>(i)), convex_index);
228  chull = VectorValues(chull,convex_index);
229  GetChullVelocity(tess, cur_w, VectorValues(neighbor_indeces[i], convex_index)
230  , static_cast<int>(i), hull_vel);
231  chull = chull + dt*hull_vel;
232  GetConvexPoints(chull, tess.GetMeshPoint(static_cast<int>(i)) + cur_w[i] * dt,
233  tess.GetWidth(static_cast<int>(i)),chull2);
234  Vector2D cm = GetCM(chull2, tess.GetMeshPoint(static_cast<int>(i)) + cur_w[i] * dt);
235  res[i] = GetCorrectedVelociy(cm, tess.GetMeshPoint(static_cast<int>(i)), w[i], dt, reduce_factor,
236  tess.GetWidth(static_cast<int>(i)),eos,cells[i],tracerstickernames);
237  }
238  cur_w = res;
239 #ifdef RICH_MPI
240  MPI_exchange_data(tess, cur_w, true);
241 #endif
242  }
243  vector<int> edges = GetBoundaryEdges(tess);
244  SlowNearBoundary(res, edges, tess, dt);
245  // check output
246  for (size_t i = 0; i < res.size(); ++i)
247  {
248  if (tess.GetWidth(static_cast<int>(i)) < abs(res[i]) * dt && abs(cells[i].velocity)*2 < abs(res[i]))
249  throw UniversalError("Velocity too large in Centroid Motion");
250  }
251  return res;
252  }
253 }
254 
255 CentroidMotion::CentroidMotion(PointMotion const& bpm,double reduction_factor, EquationOfState const& eos, size_t niter,
256  vector<string> toignore) :
257  bpm_(bpm),reduce_factor_(reduction_factor),eos_(eos),niter_(niter),toignore_(toignore){}
258 
259 vector<Vector2D> CentroidMotion::operator()(const Tessellation & tess, const vector<ComputationalCell>& cells,
260  double time, TracerStickerNames const& tracerstickernames) const
261 {
262  vector<Vector2D> res=bpm_(tess, cells, time, tracerstickernames);
263  return res;
264 }
265 
266 vector<Vector2D> CentroidMotion::ApplyFix(Tessellation const & tess, vector<ComputationalCell> const & cells, double /*time*/,
267  double dt, vector<Vector2D> const & velocities, TracerStickerNames const& tracerstickernames) const
268 {
269  return GetCorrectedVelocities(tess, velocities, dt, reduce_factor_, niter_,cells,eos_,toignore_,
270  tracerstickernames);
271 }
vector< T > VectorValues(vector< T > const &v, vector< int > const &index)
Returns only the values with indeces in index.
Definition: utils.hpp:326
void sort_index(const vector< T > &arr, vector< int > &res)
Returns the indeces of a sort.
Definition: utils.hpp:500
bool SegmentIntersection(Edge const &edge1, Edge const &edge2, Vector2D &Intersection, double eps=1e-8)
Calculates the intersection of two edges.
Definition: Edge.cpp:45
std::vector< std::string > sticker_names
The names of the stickers.
Abstract class for tessellation.
virtual int GetPointNo(void) const =0
Get Total number of mesh generating points.
CentroidMotion(PointMotion const &bpm, double reduction_factor, EquationOfState const &eos, size_t niter=2, vector< string > toignore=vector< string >())
Class constructor.
virtual int GetOriginalIndex(int point) const
Returns the original index of the duplicated point.
Definition: tessellation.cpp:5
Container for error reports.
bool PointInCell(vector< Vector2D > const &cpoints, Vector2D const &vec)
Checks if a point is inside a Voronoi cell.
Interface between two cells.
Definition: Edge.hpp:13
virtual Vector2D GetMeshPoint(int index) const =0
Returns Position of mesh generating point.
vector< Vector2D > ApplyFix(Tessellation const &tess, vector< ComputationalCell > const &cells, double time, double dt, vector< Vector2D > const &velocities, TracerStickerNames const &tracerstickernames) const
Applies a small fix to the velocity of all mesh points once the time step is known.
virtual double dp2c(double d, double p, tvector const &tracers=tvector(), vector< string > const &tracernames=vector< string >()) const =0
Calculates the speed of sound.
double max(vector< double > const &v)
returns the maximal term in a vector
Definition: utils.cpp:52
Abstract class for motion of mesh generating points.
double y
Component in the y direction.
Definition: geometry.hpp:48
tvector tracers
Tracers (can transfer from one cell to another)
virtual Edge const & GetEdge(int index) const =0
Returns edge (interface between cells)
Correction to point velocities that keeps cells round by prediction of cell center.
double pressure
Pressure.
double ScalarProd(Vector3D const &v1, Vector3D const &v2)
Scalar product of two vectors.
Definition: Vector3D.cpp:185
Base class for equation of state.
std::pair< Vector2D, Vector2D > vertices
Points at the ends of the edge.
Definition: Edge.hpp:18
virtual double GetWidth(int index) const =0
Returns the effective width of a cell.
std::vector< std::string > tracer_names
The names of the tracers.
svector stickers
Stickers (stick to the same cell)
double min(vector< double > const &v)
Returns the minimal term in a vector.
Definition: utils.cpp:44
Class for keeping the names of the tracers and stickers.
void Set(double ix, double iy)
Set vector components.
Definition: geometry.cpp:39
virtual int GetTotalSidesNumber(void) const =0
Returns the total number of faces.
std::pair< int, int > neighbors
Neighboring cells.
Definition: Edge.hpp:21
vector< Vector2D > operator()(const Tessellation &tess, const vector< ComputationalCell > &cells, double time, TracerStickerNames const &tracerstickernames) const
Calculates the velocity of all mesh points.
double abs(Vector3D const &v)
Norm of a vector.
Definition: Vector3D.cpp:44
Iter binary_find(Iter begin, Iter end, T val)
Binary search that return iterator of found object or end if not found.
Definition: utils.hpp:709
2D Mathematical vector
Definition: geometry.hpp:15
virtual vector< int > GetNeighbors(int index) const =0
Returns the indeces of the neighbors.
double x
Component in the x direction.
Definition: geometry.hpp:45
Vector2D zcross(Vector2D const &v)
Cross product of a vector in x,y plane with a unit vector in the z direction.
Definition: geometry.cpp:145
Computational cell.