ConstNumberPerProc.cpp
1 #include "ConstNumberPerProc.hpp"
2 #ifdef RICH_MPI
3 #include "../misc/serializable.hpp"
4 #include <mpi.h>
5 #endif
6 
8 
9 
10 ConstNumberPerProc::ConstNumberPerProc(OuterBoundary const& outer,double speed, double RoundSpeed, int mode,bool Rmin) :
11  outer_(outer), speed_(speed), RoundSpeed_(RoundSpeed),
12  mode_(mode), Rmin_(Rmin) {}
13 
14 #ifdef RICH_MPI
15 void ConstNumberPerProc::Update(Tessellation& tproc, Tessellation const& tlocal)const
16 {
17  int nproc = tproc.GetPointNo();
18  int rank;
19  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
20  vector<double> R(static_cast<size_t>(nproc));
21  double dx = 0;
22  double dy = 0;
23  for (size_t i = 0; i < static_cast<size_t>(nproc); ++i)
24  R[i] = tproc.GetWidth(static_cast<int>(i));
25  // Make cell rounder
26  const Vector2D& CM = tproc.GetCellCM(rank);
27  Vector2D point = tproc.GetMeshPoint(rank);
28  const double d = abs(CM - tproc.GetMeshPoint(rank));
29  double dxround = 0, dyround = 0;
30  if (d > 0.1*R[static_cast<size_t>(rank)])
31  {
32  dxround = RoundSpeed_*speed_*(CM.x - point.x);
33  dyround = RoundSpeed_*speed_*(CM.y - point.y);
34  }
35  point = CM;
36  // Find out how many points each proc has
37  vector<int> NPerProc(static_cast<size_t>(nproc));
38  int mypointnumber = tlocal.GetPointNo() + 1;
39  MPI_Gather(&mypointnumber, 1, MPI_INT, &NPerProc[0], 1, MPI_INT, 0, MPI_COMM_WORLD);
40  MPI_Bcast(&NPerProc[0], nproc, MPI_INT, 0, MPI_COMM_WORLD);
41  int IdealPerProc = 0;
42  for (size_t i = 0; i < static_cast<size_t>(nproc); ++i)
43  IdealPerProc += NPerProc[i];
44  IdealPerProc /= nproc;
45  // Move point according to density
46  if (mode_ == 1 || mode_ == 3)
47  {
48  for (size_t i = 0; i < static_cast<size_t>(nproc); ++i)
49  {
50  if (i == static_cast<size_t>(rank))
51  continue;
52  Vector2D otherpoint = tproc.GetCellCM(static_cast<int>(i));
53  double dist = sqrt((point.x - otherpoint.x)*(point.x - otherpoint.x) +
54  (point.y - otherpoint.y)*(point.y - otherpoint.y) + 0.5*R[static_cast<size_t>(rank)] * R[i]);
55  double temp = (NPerProc[i] -IdealPerProc)*R[static_cast<size_t>(rank)] * R[i]*
56  (point.x - otherpoint.x) / (pow(dist, 3)*IdealPerProc);
57  dx -= temp;
58  temp = (NPerProc[i] - IdealPerProc)*R[static_cast<size_t>(rank)] * R[i]*
59  (point.y - otherpoint.y) / (pow(dist, 3)*IdealPerProc);
60  dy -= temp;
61  }
62  }
63  double old_dx = dx;
64  double old_dy = dy;
65  dx = 0;
66  dy = 0;
67  // Moving according to pressure
68  if (mode_ == 1 || mode_ == 2)
69  {
70  const double neigheps = 0.2;
71  vector<int> neigh = tproc.GetNeighbors(rank);
72  for (size_t i = 0; i < neigh.size(); ++i)
73  {
74  if (neigh[i]>=nproc)
75  continue;
76  Vector2D otherpoint = tproc.GetMeshPoint(neigh[i]);
77  //Vector2D otherpoint=tproc.GetCellCM(neigh[i]);
78  point = tproc.GetMeshPoint(rank);
79  const double dist = tproc.GetMeshPoint(rank).distance(tproc.GetMeshPoint(neigh[i]));
80  if (dist < neigheps*std::min(R[static_cast<size_t>(rank)], R[static_cast<size_t>(neigh[i])]))
81  {
82  dx += neigheps*(point.x - tproc.GetMeshPoint(neigh[i]).x)*std::min(R[static_cast<size_t>(rank)], R[static_cast<size_t>(neigh[i])]) / dist;
83  dy += neigheps*(point.y - tproc.GetMeshPoint(neigh[i]).y)*std::min(R[static_cast<size_t>(rank)], R[static_cast<size_t>(neigh[i])]) / dist;
84  }
85  else
86  {
87  dx -= (NPerProc[static_cast<size_t>(rank)] - NPerProc[static_cast<size_t>(neigh[i])])*(otherpoint.x - point.x)*R[static_cast<size_t>(rank)] / (IdealPerProc*dist);
88  dy -= (NPerProc[static_cast<size_t>(rank)] - NPerProc[static_cast<size_t>(neigh[i])])*(otherpoint.y - point.y)*R[static_cast<size_t>(rank)] / (IdealPerProc*dist);
89  }
90  }
91  }
92  const double FarFraction = 0.65;
93  old_dx = (old_dx>0) ? std::min(old_dx, FarFraction*speed_*R[static_cast<size_t>(rank)]) : -std::min(-old_dx, FarFraction*speed_*R[static_cast<size_t>(rank)]);
94  old_dy = (old_dy > 0) ? std::min(old_dy, FarFraction*speed_*R[static_cast<size_t>(rank)]) : -std::min(-old_dy, FarFraction*speed_*R[static_cast<size_t>(rank)]);
95  dx = (dx > 0) ? std::min(dx, speed_*R[static_cast<size_t>(rank)]) : -std::min(-dx, speed_*R[static_cast<size_t>(rank)]);
96  dy = (dy > 0) ? std::min(dy, speed_*R[static_cast<size_t>(rank)]) : -std::min(-dy, speed_*R[static_cast<size_t>(rank)]);
97  // Combine the two additions
98  dx += old_dx;
99  dy += old_dy;
100  // Add the round cells
101  dx += dxround;
102  dy += dyround;
103  // Make sure not out of bounds
104  point = tproc.GetMeshPoint(rank);
105  // const double close=0.99999;
106  const double close = 0.999;
107  const double wx = tproc.GetWidth(rank);
108  const double wy = wx;
109  const Vector2D center(0.5*(outer_.GetGridBoundary(Left) + outer_.GetGridBoundary(Right)),
110  0.5*(outer_.GetGridBoundary(Up) + outer_.GetGridBoundary(Down)));
111  if (point.x + dx > outer_.GetGridBoundary(Right) - (1 - close)*wx) {
112  if (outer_.GetGridBoundary(Right) - point.x < (1 - close)*wx)
113  dx = -wx*(1 - close);
114  else
115  dx = 0.5*(outer_.GetGridBoundary(Right) - point.x);
116  }
117  if (point.x + dx < outer_.GetGridBoundary(Left) + (1 - close)*wx) {
118  if (-outer_.GetGridBoundary(Left) + point.x < (1 - close)*wx)
119  dx = wx*(1 - close);
120  else
121  dx = -0.5*(-outer_.GetGridBoundary(Left) + point.x);
122  }
123  if (point.y + dy > outer_.GetGridBoundary(Up) - (1 - close)*wy) {
124  if (outer_.GetGridBoundary(Up) - point.y < (1 - close)*wy)
125  dy = -wy*(1 - close);
126  else
127  dy = 0.5*(outer_.GetGridBoundary(Up) - point.y);
128  }
129  if (point.y + dy < outer_.GetGridBoundary(Down) + (1 - close)*wy) {
130  if (-outer_.GetGridBoundary(Down) + point.y < (1 - close)*wy)
131  dy = wy*(1 - close);
132  else
133  dy = 0.5*(outer_.GetGridBoundary(Down) - point.y);
134  }
135  Vector2D cor = tproc.GetMeshPoint(rank) + Vector2D(dx, dy);
136 
137  if (Rmin_)
138  {
139  double Rmin_1 = 0;
140  size_t Norglocal = tlocal.GetPointNo();
141  for (size_t i = 0; i < Norglocal; ++i)
142  Rmin_1 = std::max(Rmin_1, 1.0/abs(tlocal.GetMeshPoint(static_cast<int>(i))));
143  MPI_Allreduce(MPI_IN_PLACE, &Rmin_1, 1, MPI_DOUBLE, MPI_MAX, MPI_COMM_WORLD);
144  if (abs(cor) * Rmin_1 < 1.05)
145  cor = cor * 1.01 / (Rmin_1 * abs(cor));
146  }
147  // Have all processors have the same points
148  vector<double> tosend = list_serialize(vector<Vector2D>(1, cor));
149  vector<double> torecv(static_cast<size_t>(nproc) * 2);
150  MPI_Gather(&tosend[0], 2, MPI_DOUBLE, &torecv[0], 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
151  MPI_Bcast(&torecv[0], nproc * 2, MPI_DOUBLE, 0, MPI_COMM_WORLD);
152  vector<Vector2D> cortemp = list_unserialize(torecv, cor);
153  tproc.Update(cortemp);
154 }
155 #endif
double distance(Vector2D const &v1) const
Caluclates the distance from the Vector to v1.
Definition: geometry.cpp:13
virtual vector< int > Update(const vector< Vector2D > &points, bool HilbertOrder=false)=0
Update the tessellation.
Abstract class for tessellation.
virtual int GetPointNo(void) const =0
Get Total number of mesh generating points.
virtual Vector2D const & GetCellCM(int index) const =0
Returns Position of Cell&#39;s CM.
virtual Vector2D GetMeshPoint(int index) const =0
Returns Position of mesh generating point.
double max(vector< double > const &v)
returns the maximal term in a vector
Definition: utils.cpp:52
double y
Component in the y direction.
Definition: geometry.hpp:48
A class that tries to maintain a constant number of points per processor by solving eq 68 in AREPO&#39;s ...
~ConstNumberPerProc(void)
Class destructor.
virtual double GetWidth(int index) const =0
Returns the effective width of a cell.
void Update(Tessellation &tproc, Tessellation const &tlocal) const
Updates the load balance, does one iteration.
double min(vector< double > const &v)
Returns the minimal term in a vector.
Definition: utils.cpp:44
ConstNumberPerProc(OuterBoundary const &outer, double speed=0.03, double RoundSpeed=2, int mode=2, bool Rmin=false)
Class constructor.
double abs(Vector3D const &v)
Norm of a vector.
Definition: Vector3D.cpp:44
Abstract class for geometric boundary conditions for the tessellation.
2D Mathematical vector
Definition: geometry.hpp:15
virtual vector< int > GetNeighbors(int index) const =0
Returns the indeces of the neighbors.
virtual double GetGridBoundary(Directions dir) const =0
Returns the boundary coordinate.
double x
Component in the x direction.
Definition: geometry.hpp:45