simple_cell_updater.cpp
2 #include "../../misc/lazy_list.hpp"
3 #ifdef RICH_MPI
4 #include "../../mpi/mpi_commands.hpp"
5 #endif
6 
8 (const vector<pair<const SimpleCellUpdater::Condition*, const SimpleCellUpdater::Action*> > sequence, bool SR, double G) :
9  sequence_(sequence), SR_(SR), G_(G), entropy_("Entropy") {}
10 
11 SimpleCellUpdater::~SimpleCellUpdater(void)
12 {
13  for (size_t i = 0; i < sequence_.size(); ++i) {
14  delete sequence_[i].first;
15  delete sequence_[i].second;
16  }
17 }
18 
19 SimpleCellUpdater::Condition::~Condition(void) {}
20 
21 SimpleCellUpdater::Action::~Action(void) {}
22 
23 namespace
24 {
25  void EntropyFix(EquationOfState const& eos, ComputationalCell &res, size_t entropy_index, TracerStickerNames const& tracerstickernames, double &energy,
26  Extensive &extensive)
27  {
28  double new_pressure = eos.sd2p(res.tracers[entropy_index], res.density, res.tracers, tracerstickernames.tracer_names);
29  res.pressure = new_pressure;
30  double de = eos.dp2e(res.density, res.pressure) - energy;
31  energy += de;
32  extensive.energy += de * extensive.mass;
33  }
34 
35  void EntropyFixSR(EquationOfState const& eos, ComputationalCell &res, size_t entropy_index, TracerStickerNames const& tracerstickernames, double &energy,
36  Extensive &extensive, double vol)
37  {
38  double new_pressure = eos.sd2p(res.tracers[entropy_index], res.density, res.tracers, tracerstickernames.tracer_names);
39  res.pressure = new_pressure;
40  energy = eos.dp2e(res.density, res.pressure);
41  double gamma = std::sqrt(1.0 / (1 - ScalarProd(res.velocity, res.velocity)));
42  extensive.energy = extensive.mass*(energy*gamma + gamma - 1) - res.pressure*vol;
43  }
44 
45  bool HighRelativeKineticEnergy(Tessellation const& tess, size_t index, vector<Extensive> const& cells,
46  Extensive const& cell)
47  {
48  std::vector<int> neigh;
49  tess.GetNeighbors(static_cast<int>(index), neigh);
50  size_t N = neigh.size();
51  double maxDV = 0;
52  size_t Norg = static_cast<size_t>(tess.GetPointNo());
53  Vector2D Vcell = cell.momentum / cell.mass;
54  double Et = cell.energy / cell.mass - 0.5*ScalarProd(Vcell, Vcell);
55  for (size_t i = 0; i < N; ++i)
56  if (neigh[i] < static_cast<int>(Norg) || tess.GetOriginalIndex(static_cast<int>(neigh[i]))>static_cast<int>(Norg))
57  maxDV = std::max(maxDV, abs(Vcell - cells.at(static_cast<size_t>(neigh[i])).momentum / cells[static_cast<size_t>(neigh[i])].mass));
58  return 0.005*maxDV*maxDV > Et;
59  }
60 
61  void regular_update(const EquationOfState& eos, vector<Extensive>& extensives,
62  const ComputationalCell& old,
63  const CacheData& cd,
64  const size_t index,
65  ComputationalCell &res,
66  size_t entropy_index,
67  TracerStickerNames const& tracerstickernames,
68  Tessellation const& tess)
69  {
70  Extensive& extensive = extensives[index];
71  const double volume = cd.volumes[index];
72  res.density = extensive.mass / volume;
73  if (res.density < 0)
74  throw UniversalError("Negative density");
75  res.velocity = extensive.momentum / extensive.mass;
76  double energy = extensive.energy / extensive.mass -
77  0.5*ScalarProd(res.velocity, res.velocity);
78  res.stickers = old.stickers;
79  for (size_t i = 0; i < extensive.tracers.size(); ++i)
80  res.tracers[i] = extensive.tracers[i] / extensive.mass;
81  try
82  {
83  // Entropy fix if needed
84  if (entropy_index < res.tracers.size())
85  {
86  // Do we have a negative thermal energy?
87  if (energy < 0)
88  {
89  EntropyFix(eos, res, entropy_index, tracerstickernames, energy, extensive);
90  }
91  else
92  {
93  // Is the kinetic energy small?
94  if (HighRelativeKineticEnergy(tess, index, extensives, extensive))
95  {
96  EntropyFix(eos, res, entropy_index, tracerstickernames, energy, extensive);
97  }
98  else
99  {
100  double new_pressure = eos.de2p(res.density, energy, res.tracers, tracerstickernames.tracer_names);
101  double new_entropy = eos.dp2s(res.density, new_pressure, res.tracers, tracerstickernames.tracer_names);
102  if (new_entropy < 0.75*res.tracers[entropy_index])
103  {
104  EntropyFix(eos, res, entropy_index, tracerstickernames, energy, extensive);
105  }
106  else
107  {
108  // We don't need the entropy fix, update entropy
109  res.pressure = new_pressure;
110  res.tracers[entropy_index] = new_entropy;
111  extensive.tracers[entropy_index] = new_entropy * extensive.mass;
112  }
113  }
114  }
115  }
116  else
117  res.pressure = eos.de2p(res.density, energy, res.tracers, tracerstickernames.tracer_names);
118  if(!(energy>0))
119  throw UniversalError("Negative thermal energy in cell update");
120  if (!(res.pressure > 0))
121  throw UniversalError("Negative pressure in cell update");
122  }
123  catch (UniversalError &eo)
124  {
125  eo.AddEntry("Cell index", static_cast<double>(index));
126  eo.AddEntry("Volume", volume);
127  eo.AddEntry("Cell mass", extensive.mass);
128  eo.AddEntry("Cell x momentum", extensive.momentum.x);
129  eo.AddEntry("Cell y momentum", extensive.momentum.y);
130  eo.AddEntry("Cell energy", extensive.energy);
131  for (size_t i = 0; i < tracerstickernames.tracer_names.size(); ++i)
132  eo.AddEntry(tracerstickernames.tracer_names[i], extensive.tracers[i]);
133  throw;
134  }
135  }
136 
137  void regular_updateSR(const EquationOfState& eos, vector<Extensive>& extensives,
138  const ComputationalCell& old,
139  const CacheData& cd,
140  const size_t index,
141  ComputationalCell &res,
142  size_t entropy_index,
143  TracerStickerNames const& tracerstickernames,
144  Tessellation const& /*tess*/, double G)
145  {
146  Extensive& extensive = extensives[index];
147  double v = GetVelocity(extensive, G);
148  const double volume = 1.0 / cd.volumes[index];
149  res.velocity = (fastabs(extensive.momentum)*1e8 < extensive.mass) ? extensive.momentum / extensive.mass : v * extensive.momentum / abs(extensive.momentum);
150  double gamma_1 = std::sqrt(1 - ScalarProd(res.velocity, res.velocity));
151  res.density = extensive.mass *gamma_1*volume;
152  if (res.density < 0)
153  throw UniversalError("Negative density");
154  res.stickers = old.stickers;
155  for (size_t i = 0; i < extensive.tracers.size(); ++i)
156  res.tracers[i] = extensive.tracers[i] / extensive.mass;
157  if (fastabs(res.velocity) < 1e-5)
158  res.pressure = (G - 1)*((extensive.energy - ScalarProd(extensive.momentum, res.velocity))*volume
159  + (0.5*ScalarProd(res.velocity, res.velocity))*res.density);
160  else
161  res.pressure = (G - 1)*(extensive.energy*volume - ScalarProd(extensive.momentum, res.velocity)*volume
162  + (1.0 / gamma_1 - 1)*res.density);
163  // Entropy fix if needed
164  if (entropy_index < res.tracers.size())
165  {
166  // Do we have a negative thermal energy?
167  if (res.pressure < 0)
168  {
169  double enthalpy = 0;
170  EntropyFixSR(eos, res, entropy_index, tracerstickernames, enthalpy, extensive, cd.volumes[index]);
171  }
172  else
173  {
174  double new_entropy = eos.dp2s(res.density, res.pressure, res.tracers, tracerstickernames.tracer_names);
175  // We don't need the entropy fix, update entropy
176  res.tracers[entropy_index] = new_entropy;
177  extensive.tracers[entropy_index] = new_entropy * extensive.mass;
178  }
179  }
180  }
181 
182  void update_single(const Tessellation& tess,
183  const PhysicalGeometry& pg,
184  const EquationOfState& eos,
185  vector<Extensive>& extensives,
186  const vector<ComputationalCell>& old,
187  const CacheData& cd,
188  const vector<pair<const SimpleCellUpdater::Condition*, const SimpleCellUpdater::Action*> >& sequence,
189  const size_t index,
190  ComputationalCell &res,
191  size_t entropyindex,
192  TracerStickerNames const & tracerstickernames, double time, bool SR, double G)
193  {
194  for (size_t i = 0; i < sequence.size(); ++i)
195  {
196  if ((*sequence[i].first)(tess, pg, eos, extensives, old, cd, index, tracerstickernames))
197  {
198  res = (*sequence[i].second)(tess, pg, eos, extensives, old, cd, index, tracerstickernames, time);
199  return;
200  }
201  }
202  if (!SR)
203  regular_update(eos, extensives, old.at(index), cd, index, res, entropyindex, tracerstickernames, tess);
204  else
205  regular_updateSR(eos, extensives, old.at(index), cd, index, res, entropyindex, tracerstickernames, tess, G);
206  }
207 }
208 
209 vector<ComputationalCell> SimpleCellUpdater::operator()
210 (const Tessellation& tess,
211  const PhysicalGeometry& pg,
212  const EquationOfState& eos,
213  vector<Extensive>& extensives,
214  const vector<ComputationalCell>& old,
215  const CacheData& cd,
216  TracerStickerNames const& tracerstickernames,
217  double time) const
218 {
219  size_t N = static_cast<size_t>(tess.GetPointNo());
220  vector<ComputationalCell> res(N, old[0]);
221 
222  size_t tindex = old[0].tracers.size();
223  vector<string>::const_iterator it = binary_find(tracerstickernames.tracer_names.begin(),
224  tracerstickernames.tracer_names.end(), entropy_);
225  if (it != tracerstickernames.tracer_names.end())
226  tindex = static_cast<size_t>(it - tracerstickernames.tracer_names.begin());
227 #ifdef RICH_MPI
228  if (tindex < old[0].tracers.size())
229  MPI_exchange_data(tess, extensives, true);
230 #endif
231  for (size_t i = 0; i < N; ++i)
232  update_single(tess, pg, eos, extensives, old, cd, sequence_, i, res[i], tindex, tracerstickernames, time, SR_, G_);
233 #ifdef RICH_MPI
234  if (tindex < old[0].tracers.size())
235  extensives.resize(static_cast<size_t>(tess.GetPointNo()));
236 #endif
237  return res;
238 }
239 
241 (const string& sticker_name) :
242  sticker_name_(sticker_name) {}
243 
244 bool HasSticker::operator()
245 (const Tessellation& /*tess*/,
246  const PhysicalGeometry& /*pg*/,
247  const EquationOfState& /*eos*/,
248  const vector<Extensive>& /*extensives*/,
249  const vector<ComputationalCell>& cells,
250  const CacheData& /*cd*/,
251  const size_t index,
252  TracerStickerNames const& tracerstickernames) const
253 {
254  vector<string>::const_iterator it = binary_find(tracerstickernames.sticker_names.begin(), tracerstickernames.sticker_names.end(),
255  sticker_name_);
256  assert(it != tracerstickernames.sticker_names.end());
257  return cells[index].stickers[static_cast<size_t>(it - tracerstickernames.sticker_names.begin())];
258 }
259 
260 SkipUpdate::SkipUpdate(void) {}
261 
262 ComputationalCell SkipUpdate::operator()
263 (const Tessellation& /*tess*/,
264  const PhysicalGeometry& /*pg*/,
265  const EquationOfState& /*eos*/,
266  const vector<Extensive>& /*extensives*/,
267  const vector<ComputationalCell>& cells,
268  const CacheData& /*cd*/,
269  const size_t index,
270  TracerStickerNames const& /*tracerstickernames*/,
271  double/* time*/) const
272 {
273  return cells[index];
274 }
Extensive variables.
Definition: extensive.hpp:18
Simple cell updater.
Abstract class for tessellation.
virtual int GetPointNo(void) const =0
Get Total number of mesh generating points.
virtual int GetOriginalIndex(int point) const
Returns the original index of the duplicated point.
Definition: tessellation.cpp:5
virtual double de2p(double d, double e, tvector const &tracers=tvector(), vector< string > const &tracernames=vector< string >()) const =0
Calculates the pressure.
Vector2D momentum
momentum, in relativity it is = rho*h*gamma*v
Definition: extensive.hpp:31
Container for error reports.
double mass
rest mass times gamma
Definition: extensive.hpp:25
double max(vector< double > const &v)
returns the maximal term in a vector
Definition: utils.cpp:52
double energy
energy, in relativity it is = rho*h*gamma^2-P-rho
Definition: extensive.hpp:28
double y
Component in the y direction.
Definition: geometry.hpp:48
tvector tracers
Tracers (can transfer from one cell to another)
double GetVelocity(Extensive const &cell, double G)
Calculates velocity from extensive in SR.
double pressure
Pressure.
tvector tracers
tracers
Definition: extensive.hpp:34
double ScalarProd(Vector3D const &v1, Vector3D const &v2)
Scalar product of two vectors.
Definition: Vector3D.cpp:185
virtual double dp2s(double d, double p, tvector const &tracers=tvector(), vector< string > const &tracernames=vector< string >()) const =0
Calculates the entropy per unit mass.
virtual double sd2p(double s, double d, tvector const &tracers=tvector(), vector< string > const &tracernames=vector< string >()) const =0
Calculates the pressure from the netropy.
Base class for equation of state.
const CachedLazyList< double > volumes
List of cell volumes.
Definition: cache_data.hpp:81
Container for cache data.
Definition: cache_data.hpp:14
HasSticker(const string &sticker_name)
Class constructor.
std::vector< std::string > tracer_names
The names of the tracers.
svector stickers
Stickers (stick to the same cell)
SimpleCellUpdater(const vector< pair< const SimpleCellUpdater::Condition *, const SimpleCellUpdater::Action *> > sequence=vector< pair< const SimpleCellUpdater::Condition *, const SimpleCellUpdater::Action *> >(), bool SR=false, double G=0)
Class constructor.
Class for keeping the names of the tracers and stickers.
virtual double dp2e(double d, double p, tvector const &tracers=tvector(), vector< string > const &tracernames=vector< string >()) const =0
Calculates the thermal energy per unit mass.
double abs(Vector3D const &v)
Norm of a vector.
Definition: Vector3D.cpp:44
void AddEntry(std::string const &field, double value)
Adds an entry to the list.
Vector2D velocity
Velocity.
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.
Base class for physical geometry.
double fastabs(Vector2D const &v)
Norm of a vector, less accurate.
Definition: geometry.cpp:24
double x
Component in the x direction.
Definition: geometry.hpp:45
Computational cell.