PLUTO
two_shock.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Implementation of the two-shock Riemann solver for the
5  relativistic hydro equations.
6 
7  Solve the Riemann problem for the relativistic hydrodynamics
8  equations using the two-shock approach described by Mignone, Plewa
9  and Bodo (2005).
10  The formulation works with IDEAL or TAUB equation of state.
11 
12  On input, this function takes left and right primitive state vectors
13  \c state->vL and \c state->vR at zone edge \c i+1/2.
14  On output, return flux and pressure vectors at the same interface
15  \c i+1/2 (note that the \c i refers to \c i+1/2).
16 
17  Also during this step, compute maximum wave propagation speed (cmax)
18  for explicit time step computation.
19 
20  \b Reference:
21  - "The Piecewise Parabolic Method for Multidimensional Relativistic
22  Fluid Dynamics", Mignone, Plewa and Bodo, ApJS (2005) 160,199.
23 
24  \authors A. Mignone (mignone@ph.unito.it)
25  \date July 5, 2015
26 */
27 /* ///////////////////////////////////////////////////////////////////// */
28 #include "pluto.h"
29 
30 #define MAX_ITER 20
31 #define small_p 1.e-12
32 #define small_rho 1.e-12
33 #define INTERPOLATE_RAREFACTION YES
34 
35 #define accuracy 1.e-6
36 
37 static double TwoShock_Lorentz (double *U, int n);
38 static void TwoShock_Shock (double, double, double, double, double, double,
39  double, double *, double *, double *, int);
40 static double TwoShock_RarefactionSpeed (double *u, int side);
41 
42 static double qglob_r[NFLX], qglob_l[NFLX], gmmr;
43 
44 /* ********************************************************************* */
45 void TwoShock_Solver (const State_1D *state, int beg, int end,
46  double *cmax, Grid *grid)
47 /*!
48  * Solve Riemann problem for the relativistic HD equations using the
49  * two-shock Riemann solver of Mignone et al. (2005).
50  *
51  * \param[in,out] state pointer to State_1D structure
52  * \param[in] beg initial grid index
53  * \param[out] end final grid index
54  * \param[out] cmax 1D array of maximum characteristic speeds
55  * \param[in] grid pointer to array of Grid structures.
56  *
57  *********************************************************************** */
58 {
59  int iter, i, nv;
60  int k, nfail = 0, izone_fail[1024];
61  double Ustar[NFLX];
62  double gL, gR, gL1, gR1;
63  double uxR, uxR1, pR, j2R, wR, VR, VR1;
64  double uxL, uxL1, pL, j2L, wL, VL, VL1;
65  double duR, duL, p1, u1, dp, a0, a1;
66  double tauR, tauL, am, ap;
67  double *ql, *qr, *qs;
68  static double **fl, **us, **ws;
69  static double *hR, *hL, *a2L, *a2R, *cmax_loc, *cmin_loc;
70 
71  static double **fL, **fR, *prL, *prR;
72  double bmin, bmax;
73  double SL, SR;
74 
75  #if EOS == IDEAL
76  gmmr = g_gamma/(g_gamma - 1.0);
77  #endif
78 
79  if (fl == NULL){
80  fl = ARRAY_2D(NMAX_POINT, NFLX, double);
81  us = ARRAY_2D(NMAX_POINT, NVAR, double);
82  ws = ARRAY_2D(NMAX_POINT, NVAR, double);
83  cmax_loc = ARRAY_1D(NMAX_POINT, double);
84  cmin_loc = ARRAY_1D(NMAX_POINT, double);
85 
86  a2R = ARRAY_1D(NMAX_POINT, double);
87  a2L = ARRAY_1D(NMAX_POINT, double);
88  hR = ARRAY_1D(NMAX_POINT, double);
89  hL = ARRAY_1D(NMAX_POINT, double);
90 
91  fL = ARRAY_2D(NMAX_POINT, NVAR, double);
92  fR = ARRAY_2D(NMAX_POINT, NVAR, double);
93  prL = ARRAY_1D(NMAX_POINT, double);
94  prR = ARRAY_1D(NMAX_POINT, double);
95  }
96 
97 /* ----------------------------------------------------
98  compute sound speed at zone interfaces
99  ---------------------------------------------------- */
100 
101  SoundSpeed2 (state->vL, a2L, hL, beg, end, FACE_CENTER, grid);
102  SoundSpeed2 (state->vR, a2R, hR, beg, end, FACE_CENTER, grid);
103 
104 /* ---------------------------------------------------------------
105  SOLVE RIEMANN PROBLEM
106  --------------------------------------------------------------- */
107 
108  for (i = beg; i <= end; i++) {
109 
110 #if SHOCK_FLATTENING == MULTID
111  if ((state->flag[i] & FLAG_HLL) || (state->flag[i+1] & FLAG_HLL)){
112  HLL_Speed (state->vL, state->vR, a2L, a2R, &gL - i, &gR - i, i, i);
113  Flux (state->uL, state->vL, a2L, fL, prL, i, i);
114  Flux (state->uR, state->vR, a2R, fR, prR, i, i);
115 
116  a0 = MAX(fabs(gR), fabs(gL));
117  cmax[i] = a0;
118 
119  gL = MIN(0.0, gL);
120  gR = MAX(0.0, gR);
121  a0 = 1.0/(gR - gL);
122  for (nv = NFLX; nv--; ){
123  state->flux[i][nv] = gL*gR*(state->uR[i][nv] - state->uL[i][nv])
124  + gR*fL[i][nv] - gL*fR[i][nv];
125  state->flux[i][nv] *= a0;
126  }
127  state->press[i] = (gR*prL[i] - gL*prR[i])*a0;
128  continue;
129  }
130 #endif
131 
132  ql = state->vL[i];
133  qr = state->vR[i];
134 
135  gR = TwoShock_Lorentz (qr,0);
136  gL = TwoShock_Lorentz (ql,1);
137 
138  tauR = 1.0/qr[RHO];
139  tauL = 1.0/ql[RHO];
140 
141  uxR = qr[VXn];
142  uxL = ql[VXn];
143 
144  pR = qr[PRS];
145  pL = ql[PRS];
146 
147  wR = pR*tauR;
148  wL = pL*tauL;
149 
150  VR = tauR/gR;
151  VL = tauL/gL;
152 
153 /* ---------------------------------------------
154  First iteration is done out of the loop
155  --------------------------------------------- */
156 
157  #if EOS == IDEAL
158  j2R = tauR*(hR[i]*(gmmr - 2.0) + 1.0) / (gmmr*pR);
159  j2L = tauL*(hL[i]*(gmmr - 2.0) + 1.0) / (gmmr*pL);
160  #endif
161  #if EOS == TAUB
162  a0 = (5.0*hR[i] - 8.0*wR)/(2.0*hR[i] - 5.0*wR);
163  j2R = -tauR*(a0*wR + hR[i]*(1.0 - a0))/(a0*pR);
164 
165  a0 = (5.0*hL[i] - 8.0*wL)/(2.0*hL[i] - 5.0*wL);
166  j2L = -tauL*(a0*wL + hL[i]*(1.0 - a0))/(a0*pL);
167  #endif
168 
169  gR1 = sqrt(VR*VR + (1.0 - uxR*uxR)*j2R); /* RIGHT */
170  wR = VR*uxR + gR1;
171 
172  gL1 = -sqrt(VL*VL + (1.0 - uxL*uxL)*j2L); /* LEFT */
173  wL = VL*uxL + gL1;
174 
175  duR = gR1/(hR[i]*gR);
176  duL = gL1/(hL[i]*gL);
177 
178  p1 = ql[VXn] - qr[VXn] + duR*pR - duL*pL;
179  p1 /= duR - duL;
180 
181  if (p1 < 0.0) {
182  p1 = MIN(pR,pL);
183  }
184 
185 /* -----------------------------------------------
186  BEGIN iteration loop
187  ----------------------------------------------- */
188 
189  for (iter = 1; iter < MAX_ITER; iter++) {
190 
191  TwoShock_Shock (tauL, uxL, pL, gL, VL, hL[i], p1, &uxL1, &duL, &wL, -1);
192  TwoShock_Shock (tauR, uxR, pR, gR, VR, hR[i], p1, &uxR1, &duR, &wR, 1);
193 
194  /* ---- Find next approximate solution ---- */
195 
196  dp = (uxR1 - uxL1)/(duL - duR);
197  if (-dp > p1) dp = -0.5*p1;
198  p1 += dp;
199 
200  if (p1 < 0.0){
201  p1 -= dp;
202  p1 *= 0.5;
203  }
205  if ( (fabs(dp) < accuracy*p1) ) break;
206  }
207 
208 /* -----------------------------------------------
209  END iteration loop
210  ----------------------------------------------- */
211 
212  u1 = 0.5*(uxR1 + uxL1);
213 
214  /* ---- Check possible failures, and flag zones ---- */
215 
216  if (u1 != u1 || iter == MAX_ITER) {
217 
218  u1 = 0.5*(uxL + uxR);
219  p1 = 0.5*(pL + pR);
220  nfail++;
221  izone_fail[nfail] = i;
222  for (nv = NFLX; nv--; ){
223  ws[i][nv] = ql[nv];
224  }
225  continue;
226  }
227 
228 /* This switch works to prevent shear smearing, by
229  filtering noise in the velocity */
230 
231 /*
232  u1 = (fabs(u1)<1.e-13 ? 0.0:u1);
233 */
234 
235  Ustar[VXn] = u1;
236  Ustar[PRS] = p1;
237 
238 /* ------------------------------------------------------------------
239  Sample solution on x/t = 0 axis
240  ------------------------------------------------------------------ */
241 
242  if (u1 >= 0.0) { /* -- Solution is sampled to the LEFT of contact -- */
243 
244  EXPAND( ; ,
245  gL1 = gL*hL[i]/(gL*hL[i] + (p1 - pL)*(VL + wL*uxL));
246  Ustar[VXt] = ql[VXt]*gL1; ,
247  Ustar[VXb] = ql[VXb]*gL1;)
248 
249  VL1 = VL - (u1 - uxL)*wL;
250  gL1 = TwoShock_Lorentz (Ustar,2);
251  Ustar[RHO] = MAX(small_rho,1.0/(VL1*gL1));
252 
253 /* Shock or rarefaction ? */
254 
255  #if INTERPOLATE_RAREFACTION == YES
256  if (p1 < ql[PRS]){
257  am = TwoShock_RarefactionSpeed (ql, -1); /* rarefaction tail */
258  ap = TwoShock_RarefactionSpeed (Ustar, -1); /* rarefaction head */
259  am = MIN(am, ap);
260  }else{
261  ap = am = VL/wL + uxL; /* -- Shock speed -- */
262  }
263  #else
264  am = ap = VL/wL + uxL; /* -- Shock speed -- */
265  #endif
266 
267  if (am >= 0.0) { /* -- region L -- */
268  for (nv = NFLX; nv--;) ws[i][nv] = ql[nv];
269 
270  }else if (ap <= 0.0) { /* -- region L1 -- */
271 
272  for (nv = NFLX; nv--;) ws[i][nv] = Ustar[nv];
273 
274  }else{ /* Solution is inside rarefaction fan, --> interpolate */
275 
276  for (nv = NFLX; nv--;) {
277  ws[i][nv] = (am*Ustar[nv] - ap*ql[nv])/(am - ap);
278  }
279  }
280 
281  } else { /* -- Solution is sampled to the RIGHT of contact -- */
282 
283  EXPAND( ; ,
284  gR1 = gR*hR[i]/(gR*hR[i] + (p1 - pR)*(VR + wR*uxR));
285  Ustar[VXt] = qr[VXt]*gR1; ,
286  Ustar[VXb] = qr[VXb]*gR1;)
287 
288  gR1 = TwoShock_Lorentz (Ustar,3);
289  VR1 = VR - (u1 - uxR)*wR;
290  Ustar[RHO] = MAX(small_rho,1.0/(VR1*gR1));
291 
292  #if INTERPOLATE_RAREFACTION == YES
293  if (p1 < qr[PRS]){
294  am = TwoShock_RarefactionSpeed (Ustar, 1); /* rarefaction tail */
295  ap = TwoShock_RarefactionSpeed (qr, 1); /* rarefaction head */
296  ap = MAX(am, ap);
297  }else{
298  am = ap = VR/wR + uxR; /* -- Shock speed -- */
299  }
300  #else
301  am = ap = VR/wR + uxR; /* -- Shock speed -- */
302  #endif
303 
304  if (ap <= 0.0) { /* -- Shock speed -- */
305 
306  for (nv = NFLX; nv--;) ws[i][nv] = qr[nv];
307 
308  }else if (am >= 0.0){ /* region R1 */
309 
310  for (nv = NFLX; nv--;) ws[i][nv] = Ustar[nv];
311 
312  }else{ /* Solution is inside rarefaction fan, --> interpolate */
313 
314  for (nv = NFLX; nv--;) {
315  ws[i][nv] = (ap*Ustar[nv] - am*qr[nv])/(ap - am);
316  }
317  }
318  }
319 
320 /* ----------------------------------------------------------
321  Compute Fluxes
322  ---------------------------------------------------------- */
323 
324  PrimToCons (ws, us, i, i);
325  SoundSpeed2 (ws, a2R, hR, i, i, FACE_CENTER, grid);
326  Flux (us, ws, a2R, state->flux, state->press, i, i);
327  MaxSignalSpeed (ws, a2R, cmin_loc, cmax_loc, i, i);
328  a0 = MAX(fabs(cmax_loc[i]), fabs(cmin_loc[i]));
329  cmax[i] = a0;
330 
331  }
332 
333  /* -- Add artificial viscosity -- */
334 
335 #ifdef ARTIFICIAL_VISC
336  for (i = beg; i <= end; i++){
337  a0 = ARTIFICIAL_VISC*(MAX(0.0, state->vL[i][VXn] - state->vR[i][VXn]));
338  for (nv = 0; nv < NFLX; nv++) {
339  state->flux[i][nv] += a0*(state->uL[i][nv] - state->uR[i][nv]);
340  }
341  }
342 #endif
343 
344 /* ---------------------------------------------------------
345  Compute HLL flux in those zones where the Riemann
346  Solver has failed (izone_fail[k] = 1, k > 0)
347  --------------------------------------------------------- */
348 
349  for (k = 1; k <= nfail; k++){
350  print1 ("! Failure in Riemann - substituting HLL flux: ");
351  Where (izone_fail[k],NULL);
352  HLL_Solver (state, izone_fail[k]-2, izone_fail[k]+3, cmax, grid);
353  }
354 
355 }
356 #undef MAX_ITER
357 
358 /* ********************************************************************* */
359 double TwoShock_Lorentz (double *U, int n)
360 /*!
361  * Compute Lorentz gamma factor.
362  *
363  *********************************************************************** */
364 {
365 
366  double wl2, beta_fix=0.9999, scrh;
367 
368  scrh = EXPAND(U[VX1]*U[VX1], + U[VX2]*U[VX2], + U[VX3]*U[VX3]);
369 
370  if (scrh >= 1.0){
371 
372  print ("! u2 > 1 (%12.6e) in TwoShock_Lorentz\n", scrh);
373  scrh = beta_fix/sqrt(scrh);
374  EXPAND(U[VX1] *= scrh; ,
375  U[VX2] *= scrh; ,
376  U[VX3] *= scrh;)
377  scrh = beta_fix*beta_fix;
378  exit(1);
379  }
380 
381  wl2 = 1.0/(1.0 - scrh);
382 
383  return(sqrt(wl2));
384 }
385 
386 /* ********************************************************************* */
387 void TwoShock_Shock (double tau0, double u0, double p0, double g0,
388  double V0, double h0, double p1, double *u1,
389  double *dudp, double *zeta, int istate)
390 /*!
391  * Compute post shock quantities u1, dudp, zeta, for a given
392  * value of the post-shock pressure p1
393  *
394  *********************************************************************** */
395 {
396  double a,b,c, da,db,dc, dp;
397  double tau1,h1,d_htau1,g1;
398  double j2, dx;
399 
400 /* ***********************************************************
401  Use Taub Adiabat to find post-shock Enthalpy
402  and mass flux; here j2 --> 1/(j)^2
403  *********************************************************** */
404 
405  dp = p1 - p0;
406 
407  #if EOS == IDEAL
408  a = 1.0 - dp/(gmmr*p1);
409  b = 1.0 - a;
410  c = -h0*(h0 + tau0*dp);
411 
412  h1 = 0.5/a*(-b + sqrt(b*b - 4.0*a*c));
413  tau1 = (h1 - 1.0)/(gmmr*p1);
414  g1 = 2.0*h1*gmmr/(2.0*h1 - 1.0);
415 
416  j2 = h0*gmmr*tau0 + (h1*tau1 + h0*tau0)*(1.0/(h0 + h1) - 1.0);
417  j2 /= gmmr*p1;
418 
419  d_htau1 = (h1*tau1 + h0*tau0 - g1*h1*tau1);
420  d_htau1 /= (g1*p1 - dp);
421  #endif
422  #if EOS == TAUB
423  a = p0*(3.0*p1 + p0);
424  b = -h0*h0*(3.0*p1 + 2.0*p0)
425  -h0*tau0*(3.0*p1*p1 - 7.0*p1*p0 - 4.0*p0*p0) - dp;
426  c = -h0*tau0*(h0*h0 + 2.0*h0*tau0*p1 + 2.0);
427 
428  dx = 2.0*c*dp/(-b + sqrt(b*b - 4.0*a*c*dp));/* = [h\tau] */
429 
430  g1 = 2.0*c/(-b + sqrt(b*b - 4.0*a*c*dp));/* = [h\tau]/[dp] */
431  h1 = sqrt(h0*h0 + (dx + 2.0*h0*tau0)*dp);
432 
433  j2 = -g1;
434 
435  da = 3.0*p0;
436  db = -h0*h0*3.0 - h0*tau0*(6.0*p1 - 7.0*p0) - 1.0;
437  dc = c - h0*tau0*dp*2.0*h0*tau0;
438 
439  d_htau1 = -(da*dx*dx + db*dx + dc)/(2.0*a*dx + b);
440  #endif
441 
442  g1 = ((double)istate)*sqrt(V0*V0 + (1.0 - u0*u0)*j2);
443  *zeta = (V0*u0 + g1) / (1.0 - u0*u0);
444 
445 /* ***********************************************************
446  Get post-shock velocity
447  *********************************************************** */
448 
449  b = 1.0/(h0*g0 + (p1 - p0)*((*zeta)*u0 + V0));
450  *u1 = (h0*g0*u0 + (*zeta)*(p1 - p0)) * b;
451 
452 /* ***********************************************************
453  Get du/dp for next iteration
454  *********************************************************** */
455 
456  a = -0.5*(d_htau1 + j2) / g1;
457  *dudp = ((*zeta) + a - (*u1)*((*zeta)*u0 + V0 + a*u0)) * b;
458 }
459 /* ********************************************************************* */
460 double TwoShock_RarefactionSpeed (double w[], int iside)
461 /*!
462  * Compute head or tail characteristic speeds enclosing
463  * the rarefaction fan:
464  *
465  * \param[in] w a vector of primitive quantities containing
466  * the three velocities.
467  * \param[in] iside(IN) an integer specifying a left (-1) or right (+1)
468  * rarefaction wave.
469  *
470  *********************************************************************** */
471 {
472  int nv;
473  double vx, vt2, vel2;
474  double sroot, delta2, cs2[1], h[1];
475  static double **q;
476 
477  if (q == NULL) q = ARRAY_2D(10, NFLX, double);
478 
479  for (nv = 0; nv < NFLX; nv++) q[0][nv] = w[nv];
480 
481  SoundSpeed2(q, cs2, h, 0, 0, FACE_CENTER, NULL);
482 
483  vx = w[VXn];
484  vt2 = EXPAND(0.0, + w[VXt]*w[VXt], + w[VXb]*w[VXb]);
485  vel2 = vx*vx + vt2;
486 
487  sroot = cs2[0]*(1.0 - vx*vx - vt2*cs2[0])*(1.0 - vel2); /* this is eta/gamma */
488 
489  if (sroot < 0.0){
490  print ("! sroot < 0 in RIemann \n");
491  for (nv = 0; nv < NFLX; nv++){
492  print ("%d %12.6e %12.6e\n",nv, qglob_l[nv], qglob_r[nv]);
493  }
494  QUIT_PLUTO(1);
495  }
496  sroot = sqrt(sroot); /*this is eta/gamma */
497 
498  delta2 = 1.0 - vel2*cs2[0];
499  return( (vx*(1.0 - cs2[0]) + (double)iside*sroot)/delta2);
500 }
501 
502 #undef MAX_ITER
503 #undef small_p
504 #undef small_rho
505 #undef accuracy
506 #undef INTERPOLATE_RAREFACTION
static Data_Arr V0
Definition: failsafe.c:4
static double a
Definition: init.c:135
#define MAX(a, b)
Definition: macros.h:101
double g_gamma
Definition: globals.h:112
static double qglob_l[NFLX]
Definition: two_shock.c:42
#define VX2
Definition: mod_defs.h:29
double ** flux
upwind flux computed with the Riemann solver
Definition: structs.h:149
static int n
Definition: analysis.c:3
#define ARTIFICIAL_VISC
void print1(const char *fmt,...)
Definition: amrPluto.cpp:511
void Flux(double **u, double **w, double *a2, double **fx, double *p, int beg, int end)
Definition: fluxes.c:23
void TwoShock_Solver(const State_1D *state, int beg, int end, double *cmax, Grid *grid)
Definition: two_shock.c:40
#define RHO
Definition: mod_defs.h:19
tuple scrh
Definition: configure.py:200
#define MAX_ITER
Definition: two_shock.c:30
static double gmmr
Definition: two_shock.c:42
int g_maxRiemannIter
Maximum number of iterations for iterative Riemann Solver.
Definition: globals.h:93
double ** vR
Primitive variables to the right of the interface, .
Definition: structs.h:139
#define VX1
Definition: mod_defs.h:28
int VXb
Definition: globals.h:73
void SoundSpeed2(double **v, double *cs2, double *h, int beg, int end, int pos, Grid *grid)
Definition: eos.c:16
#define MIN(a, b)
Definition: macros.h:104
static void TwoShock_Shock(double, double, double, double, double, double, double, double *, double *, double *, int)
Definition: two_shock.c:387
#define accuracy
Definition: two_shock.c:35
#define NFLX
Definition: mod_defs.h:32
#define FACE_CENTER
Definition: pluto.h:206
Definition: structs.h:78
list vel2
Definition: Sph_disk.py:39
int VXt
Definition: globals.h:73
unsigned char * flag
Definition: structs.h:168
void Where(int, Grid *)
Definition: tools.c:235
int k
Definition: analysis.c:2
void print(const char *fmt,...)
Definition: amrPluto.cpp:497
static double qglob_r[NFLX]
Definition: two_shock.c:42
tuple c
Definition: menu.py:375
int VXn
Definition: globals.h:73
double ** uR
same as vR, in conservative vars
Definition: structs.h:145
PLUTO main header file.
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
long int NMAX_POINT
Maximum number of points among the three directions, boundaries excluded.
Definition: globals.h:62
void PrimToCons(double **uprim, double **ucons, int ibeg, int iend)
Definition: mappers.c:26
int i
Definition: analysis.c:2
Riemann_Solver HLL_Solver
Definition: mod_defs.h:106
void HLL_Speed(double **vL, double **vR, double *a2L, double *a2R, double *SL, double *SR, int beg, int end)
Definition: hll_speed.c:24
#define VX3
Definition: mod_defs.h:30
#define small_rho
Definition: two_shock.c:32
double ** vL
Primitive variables to the left of the interface, .
Definition: structs.h:136
double * press
Upwind pressure term computed with the Riemann solver.
Definition: structs.h:164
void MaxSignalSpeed(double **v, double *cs2, double *cmin, double *cmax, int beg, int end)
Definition: eigenv.c:34
#define FLAG_HLL
Use HLL Riemann solver.
Definition: pluto.h:181
#define ARRAY_2D(nx, ny, type)
Definition: prototypes.h:171
#define NVAR
Definition: pluto.h:609
static Runtime q
static double TwoShock_Lorentz(double *U, int n)
Definition: two_shock.c:359
#define QUIT_PLUTO(e_code)
Definition: macros.h:125
static double TwoShock_RarefactionSpeed(double *u, int side)
double ** uL
same as vL, in conservative vars
Definition: structs.h:144