ersig.cpp
1 #include <algorithm>
2 #include <cmath>
3 #include "ersig.hpp"
4 #include "ideal_gas.hpp"
5 #include "hydrodynamics.hpp"
6 #include "../../misc/bisection.hpp"
7 #include "../../misc/universal_error.hpp"
8 
9 using namespace std;
10 
11 namespace {
12  double phugo(double v2,
13  double d1,
14  double p1,
15  double g)
16  {
17  return (4*p1 + d1*(1 + g)*pow(v2,2) + sqrt(d1)*v2*
18  sqrt(16*g*p1 + d1*pow(1 + g,2)*pow(v2,2)))/4.;
19  }
20 
21  double vhugo(double p2,
22  double d1,
23  double p1,
24  double g)
25  {
26  return sqrt(2.)*(p2-p1)/sqrt(d1*(p2*(g+1)+p1*(g-1)));
27  }
28 
29  double visen(double p2,
30  double d1,
31  double p1,
32  double g)
33  {
34  return (2*sqrt(g)*pow(p1,1/g/2)*
35  (pow(p2,(g-1)/g/2)-pow(p1,(g-1)/g/2)))/
36  (sqrt(d1)*(g-1));
37  }
38 
39  double vhydro(double p2,
40  double d1,
41  double p1,
42  double g)
43  {
44  if(p2>p1)
45  return vhugo(p2,d1,p1,g);
46  else
47  return visen(p2,d1,p1,g);
48  }
49 
50  double left_velocity(double p,
51  Primitive const& upstream,
52  double g)
53  {
54  const double d1 = upstream.Density;
55  const double p1 = upstream.Pressure;
56  const double v1 = upstream.Velocity.x;
57  return v1 - vhydro(p,d1,p1,g);
58  }
59 
60  double right_velocity(double p,
61  Primitive const& upstream,
62  double g)
63  {
64  const double d1 = upstream.Density;
65  const double p1 = upstream.Pressure;
66  const double v1 = upstream.Velocity.x;
67  return v1 + vhydro(p,d1,p1,g);
68  }
69 
70  double eval_trans_eqn(double p,
71  Primitive const& left,
72  Primitive const& right,
73  double g)
74  {
75  return right_velocity(p,right,g) - left_velocity(p,left,g);
76  }
77 
79  class TransEqn: public Func1Var
80  {
81  public:
82 
88  TransEqn(Primitive const& left,
89  Primitive const& right,
90  double g):
91  left_(left),
92  right_(right),
93  g_(g) {}
94 
99  double eval(double p) const
100  {
101  return eval_trans_eqn(p,left_,right_,g_);
102  }
103 
104  private:
105 
106  const Primitive left_;
107  const Primitive right_;
108  const double g_;
109  };
110 
111  double ps_two_rarefactions(Primitive const& left,
112  Primitive const& right,
113  double g)
114  {
115  const double dl = left.Density;
116  const double pl = left.Pressure;
117  const double vl = left.Velocity.x;
118  const double dr = right.Density;
119  const double pr = right.Pressure;
120  const double vr = right.Velocity.x;
121  const double temp =
122  (2*(sqrt(g*dr*pl)+sqrt(g*dl*pr))+
123  sqrt(dl*dr)*(g-1)*(vl-vr))/
124  (2*(sqrt(g*dr)*pow(pl,1/g/2)+
125  sqrt(g*dl)*pow(pr,1/g/2)));
126  if(temp<0){
127  throw UniversalError("Vacuum formed");
128  }
129  const double res = pow(temp,2*g/(g-1));
130  return res;
131  }
132 }
133 
134 namespace{
135  class PVContact
136  {
137  public:
138 
143  PVContact(double p, double v):
144  pressure(p), velocity(v) {}
145 
147  const double pressure;
148 
150  const double velocity;
151  };
152 }
153 
154 namespace{
155  PVContact calc_contact_pv(Primitive const& left,
156  Primitive const& right,
157  double g)
158  {
159  using namespace std;
160 
161  const double tol = 1e-6;
162 
163  const double vlpr = left_velocity(right.Pressure, left, g);
164  const double vrpl = right_velocity(left.Pressure, right, g);
165  double ps = 0;
166  if(min(left.Velocity.x,vlpr)>
167  max(right.Velocity.x,vrpl)){
168  // Two shocks
169  const double plvr = phugo(left.Velocity.x-right.Velocity.x,
170  left.Density,left.Pressure,g);
171  const double prvl = phugo(left.Velocity.x-right.Velocity.x,
172  right.Density,right.Pressure,g);
173  const TransEqn eqn(left,right,g);
174  try{
175  ps = bisection(eqn,max(left.Pressure,right.Pressure),
176  2*max(plvr,prvl),tol);
177  }
178  catch(UniversalError& eo){
179  eo.AddEntry("caught in two shock section of ersig",0);
180  eo.AddEntry("left density",left.Density);
181  eo.AddEntry("right density",right.Density);
182  eo.AddEntry("left pressure",left.Pressure);
183  eo.AddEntry("right pressure",right.Pressure);
184  eo.AddEntry("left x velocity",left.Velocity.x);
185  eo.AddEntry("right x velocity",right.Velocity.y);
186  eo.AddEntry("rethrown",0);
187  throw;
188  }
189  }
190  else if(max(left.Velocity.x,vlpr)<
191  min(right.Velocity.x,vrpl)){
192  // Two rarefactions
193  ps = ps_two_rarefactions(left, right, g);
194  }
195  else{
196  // Shock rarefaction
197  const TransEqn eqn(left, right, g);
198  ps = bisection(eqn,
199  min(left.Pressure, right.Pressure),
200  max(left.Pressure, right.Pressure),
201  tol);
202  }
203  const double vs = 0.5*(left_velocity(ps,left,g)+right_velocity(ps,right,g));
204  return PVContact(ps,vs);
205  }
206 }
207 
208 // Self similar spatial profiles
209 
210 // Shocks
211 
212 namespace {
213  double shock_speed(double p2,
214  double d1,
215  double p1,
216  double g)
217  {
218  return sqrt(g*(p2+p1)+p2-p1)/sqrt(2*d1);
219  }
220 
221  double dhugo(double p2,
222  double d1,
223  double p1,
224  double g)
225  {
226  return (d1*((-1 + g)*p1 + (1 + g)*p2))/((1 + g)*p1 + (-1 + g)*p2);
227  }
228 
229  Primitive move_on_hugoniot(double ps,
230  Primitive const& upstream,
231  double g)
232  {
233  const double ds = dhugo(ps,
234  upstream.Density,
235  upstream.Pressure, g);
236  const Vector2D vs(vhugo(ps,
237  upstream.Density,
238  upstream.Pressure,g),
239  upstream.Velocity.y);
240  return CalcPrimitive(ds,ps, vs, IdealGas(g));
241  }
242 
243  class HydroProf
244  {
245  public:
246 
247  virtual Primitive getHydroVars(double v) const = 0;
248 
249  virtual ~HydroProf(void) {}
250  };
251 
252  Primitive x_rest_frame(Primitive const& source)
253  {
254  Primitive res =source;
255  res.Velocity.x = 0;
256  return res;
257  }
258 }
259 
261 namespace {
262  class ShockProf
263  {
264  public:
265 
266  ShockProf
267  (double p2,
268  Primitive const& upstream,
269  double g):
270  vs_(shock_speed(p2,
271  upstream.Density,
272  upstream.Pressure,g)),
273  upstream_(x_rest_frame(upstream)),
274  downstream_
275  (move_on_hugoniot(p2,upstream,g)) {}
276 
277  Primitive getHydroVars(double v) const
278  {
279  if(v>vs_)
280  return upstream_;
281  else
282  return downstream_;
283  }
284 
285  private:
286 
287  const double vs_;
288  const Primitive upstream_;
289  const Primitive downstream_;
290  };
291 }
292 
293 /*class ShockProf: public HydroProf
294  {
295  public:
296 
297  ShockProf(double p2,
298  Primitive const& upstream,
299  double g):
300  vs_(shock_speed(p2,
301  upstream.Density,
302  upstream.Pressure,g)),
303  upstream_(x_rest_frame(upstream)),
304  downstream_
305  (move_on_hugoniot(p2,upstream,g)) {}
306 
307  Primitive getHydroVars(double v) const
308  {
309  if(v>vs_)
310  return upstream_;
311  else
312  return downstream_;
313  }
314 
315  private:
316 
317  const double vs_;
318  const Primitive upstream_;
319  const Primitive downstream_;
320  };*/
321 
322 // Isentropes
323 
324 namespace {
325  double disen(double p2,
326  double d1,
327  double p1,
328  double g)
329  {
330  return d1*pow(p2/p1,1/g);
331  }
332 
333  Primitive move_on_isentrope(double pr,
334  Primitive const& upstream,
335  double g)
336  {
337  const double dr = disen(pr,
338  upstream.Density,
339  upstream.Pressure,g);
340  const Vector2D vr(visen(pr,
341  upstream.Density,
342  upstream.Pressure,g),
343  upstream.Velocity.y);
344  return CalcPrimitive(dr,pr,vr,IdealGas(g));
345  }
346 }
347 
348 namespace {
349  class IsenProf
350  {
351  public:
352 
353  IsenProf
354  (double p2,
355  Primitive const& upstream,
356  double g):
357  g_(g),
358  upstream_(x_rest_frame(upstream)),
359  downstream_
360  (move_on_isentrope(p2, upstream,g)) {}
361 
362  Primitive getHydroVars(double v) const
363  {
364  if(v>upstream_.SoundSpeed)
365  return upstream_;
366  else if(v<downstream_.SoundSpeed+downstream_.Velocity.x)
367  return downstream_;
368  else{
369  const double u = (v-upstream_.SoundSpeed)*2/(1+g_);
370  const double c = upstream_.SoundSpeed+(g_-1)*u/2;
371  const double p = upstream_.Pressure*
372  pow(c/upstream_.SoundSpeed,2*g_/(g_-1));
373  const double d = disen(p,upstream_.Density,
374  upstream_.Pressure, g_);
375  return CalcPrimitive(d,p,
376  Vector2D(u,upstream_.Velocity.y),
377  IdealGas(g_));
378  }
379  }
380 
381  private:
382  const double g_;
383  const Primitive upstream_;
384  const Primitive downstream_;
385  };
386 }
387 
388 /*class IsenProf: public HydroProf
389  {
390  public:
391 
392  IsenProf(double p2,
393  Primitive const& upstream,
394  double g):
395  g_(g),
396  upstream_(x_rest_frame(upstream)),
397  downstream_
398  (move_on_isentrope(p2, upstream,g)) {}
399 
400  Primitive getHydroVars(double v) const
401  {
402  if(v>upstream_.SoundSpeed)
403  return upstream_;
404  else if(v<downstream_.SoundSpeed)
405  return downstream_;
406  else{
407  const double u = (v-upstream_.SoundSpeed)*2/(1+g_);
408  const double c = upstream_.SoundSpeed+(g_-1)*u/2;
409  const double p = upstream_.Pressure*
410  pow(c/upstream_.SoundSpeed,2*g_/(g_-1));
411  const double d = disen(p,upstream_.Density,
412  upstream_.Pressure, g_);
413  return CalcPrimitive(d,p,
414  Vector2D(u,upstream_.Velocity.y),
415  IdealGas(g_));
416  }
417  }
418 
419  private:
420  const double g_;
421  const Primitive upstream_;
422  const Primitive downstream_;
423  };*/
424 
425 namespace{
426  class GeneralProf
427  {
428  public:
429 
430  GeneralProf
431  (double p2,
432  Primitive const& upstream,
433  double g):
434  hugo_(max(upstream.Pressure,p2),upstream,g),
435  isen_(min(upstream.Pressure,p2),upstream,g),
436  hugo_flag_(p2>upstream.Pressure) {}
437 
438  Primitive getHydroVars(double v) const
439  {
440  if(hugo_flag_)
441  return hugo_.getHydroVars(v);
442  else
443  return isen_.getHydroVars(v);
444  }
445 
446  private:
447 
448  const ShockProf hugo_;
449  const IsenProf isen_;
450  const bool hugo_flag_;
451  };
452 }
453 
454 /*class GeneralProf: public HydroProf
455  {
456  public:
457 
458  GeneralProf(double p2,
459  Primitive const& upstream,
460  double g):
461  hugo_flag_(p2>upstream.Pressure),
462  hugo_(max(upstream.Pressure,p2),upstream,g),
463  isen_(min(upstream.Pressure,p2),upstream,g) {}
464 
465  Primitive getHydroVars(double v) const
466  {
467  if(hugo_flag_)
468  return hugo_.getHydroVars(v);
469  else
470  return isen_.getHydroVars(v);
471  }
472 
473  private:
474 
475  const bool hugo_flag_;
476  const ShockProf hugo_;
477  const IsenProf isen_;
478  };*/
479 
480 namespace {
481  class RiemannProfile
482  {
483  public:
484  RiemannProfile(Primitive const& left,
485  Primitive const& right,
486  double g):
487  contact_(calc_contact_pv(left,right,g)),
488  left_prof_(contact_.pressure,
489  left, g),
490  right_prof_(contact_.pressure,
491  right, g),
492  left_(left), right_(right) {}
493 
494  Primitive getHydroVars(double v) const
495  {
496  if(v>contact_.velocity){
497  Primitive res = right_prof_.getHydroVars
498  (v-right_.Velocity.x);
499  res.Velocity.x += right_.Velocity.x;
500  return res;
501  }
502  else{
503  Primitive res = left_prof_.getHydroVars
504  (left_.Velocity.x - v);
505  res.Velocity.x = left_.Velocity.x -
506  res.Velocity.x;
507  return res;
508  }
509  }
510 
511  private:
512  const PVContact contact_;
513  const GeneralProf left_prof_;
514  const GeneralProf right_prof_;
515  const Primitive left_;
516  const Primitive right_;
517  };
518 }
519 
520 /*class RiemannProfile//: public HydroProf
521  {
522  public:
523 
524  RiemannProfile(Primitive const& left,
525  Primitive const& right,
526  double g):
527  contact_(calc_contact_pv(left,right,g)),
528  left_prof_(contact_.pressure,
529  left, g),
530  right_prof_(contact_.pressure,
531  right, g),
532  left_(left), right_(right) {}
533 
534  Primitive getHydroVars(double v) const
535  {
536  if(v>contact_.velocity){
537  Primitive res = right_prof_.getHydroVars
538  (v-right_.Velocity.x);
539  res.Velocity.x += right_.Velocity.x;
540  return res;
541  }
542  else{
543  Primitive res = left_prof_.getHydroVars
544  (left_.Velocity.x - v);
545  res.Velocity.x = left_.Velocity.x -
546  res.Velocity.x;
547  return res;
548  }
549  }
550 
551  private:
552  const PVContact contact_;
553  const GeneralProf left_prof_;
554  const GeneralProf right_prof_;
555  const Primitive left_;
556  const Primitive right_;
557  };*/
558 
559 ERSIG::ERSIG(double g,
560  string const& vacuum_behaviour):
561  g_(g), vacuum_behaviour_(vacuum_behaviour) {}
562 
563 Conserved ERSIG::operator()
564 (Primitive const& left,
565  Primitive const& right,
566  double velocity) const
567 {
568  try{
569  const Primitive inter =
570  RiemannProfile(left,right,g_).getHydroVars(velocity);
571 
572  const Conserved res = Primitive2Flux(inter,Vector2D(1,0)) -
573  velocity*Primitive2Conserved(inter);
574 
575  return res;
576  }
577  catch(UniversalError& eo){
578  if(eo.GetErrorMessage()=="Vacuum formed"){
579  if(vacuum_behaviour_=="zero flux")
580  return Conserved();
581  }
582 
583  eo.AddEntry("ERSIG::Solve data starts here",0);
584  eo.AddEntry("left density",left.Density);
585  eo.AddEntry("left pressure",left.Pressure);
586  eo.AddEntry("left x velocity",left.Velocity.x);
587  eo.AddEntry("left y velocity",left.Velocity.y);
588  eo.AddEntry("right density",right.Density);
589  eo.AddEntry("right pressure",right.Pressure);
590  eo.AddEntry("right x velocity",right.Velocity.x);
591  eo.AddEntry("right y velocity",right.Velocity.y);
592  throw;
593  }
594 }
Set of conserved variables (extensive)
double Density
Density.
Ideal gas equation of state.
Definition: ideal_gas.hpp:13
Ideal gas equation of state.
double SoundSpeed
Speed of sound.
Container for error reports.
Primitive CalcPrimitive(double density, double pressure, Vector2D const &velocity, EquationOfState const &eos)
Calculates the primitive variables.
ERSIG(double g, string const &vacuum_behaviour="throw exception")
Class constructor.
Definition: ersig.cpp:559
Vector2D Velocity
Velocity.
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
Exact Riemann solver for ideal gas equation of state.
Hydrodynamical relations.
Conserved Primitive2Conserved(Primitive const &p)
Converts primitive variables to conserved intensive.
Conserved Primitive2Flux(Primitive const &p, Vector2D const &n)
Converts primitive variables to flux.
double bisection(Func1Var const &f, double xl, double xr, double tol=1e-6)
Solves a monotonous transcendental equation using the bisection method.
Definition: bisection.cpp:34
Scalar function of a single variable.
Definition: func_1_var.hpp:9
double min(vector< double > const &v)
Returns the minimal term in a vector.
Definition: utils.cpp:44
double Pressure
Pressure.
void AddEntry(std::string const &field, double value)
Adds an entry to the list.
Primitive hydrodynamic variables.
2D Mathematical vector
Definition: geometry.hpp:15
double x
Component in the x direction.
Definition: geometry.hpp:45
std::string const & GetErrorMessage(void) const
Returns the error message.