PLUTO
flag_shock.c
Go to the documentation of this file.
1 /* ///////////////////////////////////////////////////////////////////// */
2 /*!
3  \file
4  \brief Shock finding algorithm.
5 
6  Search and flag computational zones lying in a shock wave.
7  The flagging strategy is based on two switches designed to detect
8  the presence of compressive motion or shock waves in the fluid:
9  \f[
10  \nabla\cdot\vec{v} < 0 \qquad{\rm and}\qquad
11  \Delta x\frac{|\nabla p|}{p} > \epsilon_p
12  \f]
13  where \f$\epsilon_p\f$ sets the shock strength.
14  At the discrete level we replace the two conditions by
15  \f[
16  \sum_d \frac{ A_{\vec{i}+\HALF\hvec{e}_d}v_{d,\vec{i}+\HALF\hvec{e}_d}
17  -A_{\vec{i}-\HALF\hvec{e}_d}v_{d,\vec{i}-\HALF\hvec{e}_d} }
18  {\Delta{\cal V}_{d,\vec{i}}} < 0
19  \qquad{\rm and}\qquad
20  \sum_{d} \left|p_{\vec{i}+\hvec{e}_d} - p_{\vec{i}-\hvec{e}_d}\right|
21  <
22  \epsilon_p \min_d\left(p_{\vec{i}+\hvec{e}_d},
23  p_{\vec{i}-\hvec{e}_d},p_{\vec{i}}\right)
24  \f]
25  where \f$\hvec{i} = (i,j,k)\f$ is a vector of integer numbers
26  giving the position of a computational zone, while \f$\hvec{e}_d =
27  (\delta_{1d},\delta_{2d},\delta_{3d})\f$ is a unit vector in the direction
28  given by \c d.
29  Once a zone has been tagged as lying in a shock, different flags may be
30  switched on or off to control the update strategy in these critical regions.
31 
32  This function can be called called when:
33  - \c SHOCK_FLATTENING has been set to \c MULTID: in this case shocked zones
34  are tagged with \c FLAG_MINMOD and \c FLAG_HLL that will later
35  be used to force the reconstruction with the minmod limiter
36  and the Riemann solver to HLL.
37  - \c ENTROPY_SWITCH has been turned on: this flag will be checked later in
38  the ConsToPrim() functions in order to recover pressure from the
39  entropy density rather than from the total energy density.
40  The update process is:
41 
42  - start with a vector of primitive variables <tt> {V,s} </tt>
43  where \c s is the entropy;
44  - set boundary condition on \c {V};
45  - compute \c {s} from \c {V};
46  - flag zones where entropy may be used (flag = 1);
47  - evolve equations for one time step;
48  - convert <tt> {U,S} </tt> to primitive:
49  \code
50  if (flag == 0) { // Use energy
51  p = p(E)
52  s = s(p)
53  }else{ // use entropy
54  p = p(S)
55  E = E(p)
56  }
57  \endcode
58 
59  \b Reference
60  - "Maintaining Pressure Positivity in Magnetohydrodynamics Simulations"
61  Balsara \& Spicer, JCP (1999) 148, 133
62 
63  \authors A. Mignone (mignone@ph.unito.it)
64  \date July 28, 2015
65 */
66 /* ///////////////////////////////////////////////////////////////////// */
67 #include"pluto.h"
68 
69 #ifndef EPS_PSHOCK_FLATTEN
70  #define EPS_PSHOCK_FLATTEN 5.0
71 #endif
72 
73 #ifndef EPS_PSHOCK_ENTROPY
74  #define EPS_PSHOCK_ENTROPY 0.05
75 #endif
76 
77 #if (SHOCK_FLATTENING == MULTID) || ENTROPY_SWITCH
78 /* *************************************************************** */
79 void FlagShock (const Data *d, Grid *grid)
80 /*!
81  *
82  *
83  ***************************************************************** */
84 {
85  int i, j, k, nv;
86  int ip, jp, kp;
87  double divv, gradp, pt_min;
88  double dpx1, *dx1, *dV1, ***vx1, pt_min1, dvx1;
89  double dpx2, *dx2, *dV2, ***vx2, pt_min2, dvx2;
90  double dpx3, *dx3, *dV3, ***vx3, pt_min3, dvx3;
91 
92  double *dVx, *dVy, *dVz;
93  double *Ar, *Ath, *r, *th, s;
94  static double ***pt;
95 
96 /* ----------------------------------------------------
97  0. Define pointers to variables and allocate memory
98  ---------------------------------------------------- */
99 
100  dx1 = grid[IDIR].dx; dV1 = grid[IDIR].dV;
101  dx2 = grid[JDIR].dx; dV2 = grid[JDIR].dV;
102  dx3 = grid[KDIR].dx; dV3 = grid[KDIR].dV;
103 
104  Ar = grid[IDIR].A;
105  r = grid[IDIR].x;
106  Ath = grid[JDIR].A;
107  th = grid[JDIR].x;
108 
109  EXPAND(vx1 = d->Vc[VX1]; ,
110  vx2 = d->Vc[VX2]; ,
111  vx3 = d->Vc[VX3];)
112 
113  if (pt == NULL) pt = ARRAY_3D(NX3_MAX, NX2_MAX, NX1_MAX, double);
114 
115 /* --------------------------------------------------------
116  1. Compute total pressure and flag, initially all zones
117  with ENTROPY_SWITCH.
118  -------------------------------------------------------- */
119 
120  TOT_LOOP(k,j,i){
121 #if EOS == ISOTHERMAL
122  pt[k][j][i] = d->Vc[RHO][k][j][i]*g_isoSoundSpeed*g_isoSoundSpeed;
123 #else
124  #if HAVE_ENERGY
125  pt[k][j][i] = d->Vc[PRS][k][j][i];
126  #endif
127 #endif
128 
129 #if (ENTROPY_SWITCH == SELECTIVE) || (ENTROPY_SWITCH == ALWAYS)
130  d->flag[k][j][i] |= FLAG_ENTROPY;
131 #endif
132  }
133 
134 /* ----------------------------------------------
135  2. Track zones lying in a shock
136  ---------------------------------------------- */
137 
138  for (k = KOFFSET; k < NX3_TOT-KOFFSET; k++){
139  for (j = JOFFSET; j < NX2_TOT-JOFFSET; j++){
140  for (i = IOFFSET; i < NX1_TOT-IOFFSET; i++){
141 
142  /* -- Compute divergence of velocity -- */
143 
144  #if GEOMETRY == CARTESIAN
145 
146  D_EXPAND(dvx1 = vx1[k][j][i + 1] - vx1[k][j][i - 1]; ,
147  dvx2 = vx2[k][j + 1][i] - vx2[k][j - 1][i]; ,
148  dvx3 = vx3[k + 1][j][i] - vx3[k - 1][j][i];)
149 
150  #elif GEOMETRY == CYLINDRICAL
151 
152  D_EXPAND(dvx1 = Ar[i] *(vx1[k][j][i + 1] + vx1[k][j][i])
153  - Ar[i-1]*(vx1[k][j][i - 1] + vx1[k][j][i]); ,
154  dvx2 = vx2[k][j + 1][i] - vx2[k][j - 1][i]; ,
155  dvx3 = vx3[k + 1][j][i] - vx3[k - 1][j][i];)
156 
157  #elif GEOMETRY == POLAR
158 
159  D_EXPAND(dvx1 = Ar[i] *(vx1[k][j][i + 1] + vx1[k][j][i])
160  - Ar[i-1]*(vx1[k][j][i - 1] + vx1[k][j][i]); ,
161  dvx2 = (vx2[k][j + 1][i] - vx2[k][j - 1][i])/r[i]; ,
162  dvx3 = vx3[k + 1][j][i] - vx3[k - 1][j][i];)
163 
164  #elif GEOMETRY == SPHERICAL
165 
166  D_EXPAND(dvx1 = Ar[i] *(vx1[k][j][i + 1] + vx1[k][j][i])
167  - Ar[i-1]*(vx1[k][j][i - 1] + vx1[k][j][i]); ,
168  dvx2 = ( Ath[j] *(vx2[k][j + 1][i] + vx2[k][j][i])
169  - Ath[j-1]*(vx2[k][j - 1][i] + vx2[k][j][i]))/fabs(r[i]); ,
170  s = th[j];
171  dvx3 = (vx3[k + 1][j][i] - vx3[k - 1][j][i])/(r[i]*sin(s));)
172 
173  #endif
174 
175  divv = D_EXPAND(dvx1/dV1[i], + dvx2/dV2[j], + dvx3/dV3[k]);
176 
177  if (divv < 0.0){
178 
179  /* -----------------------------------------------
180  Compute undivided difference of the total
181  pressure and minimum value in neighbour zones
182  ----------------------------------------------- */
183 
184  pt_min = pt[k][j][i];
185  D_EXPAND(pt_min1 = MIN(pt[k][j][i+1], pt[k][j][i-1]); ,
186  pt_min2 = MIN(pt[k][j+1][i], pt[k][j-1][i]); ,
187  pt_min3 = MIN(pt[k+1][j][i], pt[k-1][j][i]); )
188 
189  D_EXPAND(pt_min = MIN(pt_min, pt_min1); ,
190  pt_min = MIN(pt_min, pt_min2); ,
191  pt_min = MIN(pt_min, pt_min3);)
192 
193  D_EXPAND(dpx1 = fabs(pt[k][j][i+1] - pt[k][j][i-1]); ,
194  dpx2 = fabs(pt[k][j+1][i] - pt[k][j-1][i]); ,
195  dpx3 = fabs(pt[k+1][j][i] - pt[k-1][j][i]);)
196 
197  gradp = D_EXPAND(dpx1, + dpx2, + dpx3);
198 
199  #if SHOCK_FLATTENING == MULTID
200  if (gradp > EPS_PSHOCK_FLATTEN*pt_min) {
201  d->flag[k][j][i] |= FLAG_HLL;
202 
203  d->flag[k][j][i] |= FLAG_MINMOD;
204  D_EXPAND(
205  d->flag[k][j][i+1] |= FLAG_MINMOD;
206  d->flag[k][j][i-1] |= FLAG_MINMOD; ,
207  d->flag[k][j-1][i] |= FLAG_MINMOD;
208  d->flag[k][j+1][i] |= FLAG_MINMOD; ,
209  d->flag[k-1][j][i] |= FLAG_MINMOD;
210  d->flag[k+1][j][i] |= FLAG_MINMOD;)
211  }
212  #endif
213 
214  /* -----------------------------------------------------
215  When using entropy, we unflag those zones lying in
216  a shock as well as one neighbour cells to the left
217  and to the right for each dimension.
218  ----------------------------------------------------- */
219 
220  #if ENTROPY_SWITCH == SELECTIVE
221  if (gradp > EPS_PSHOCK_ENTROPY*pt_min) { /* -- unflag zone -- */
222  d->flag[k][j][i] &= ~(FLAG_ENTROPY);
223  D_EXPAND(
224  d->flag[k][j][i-1] &= ~(FLAG_ENTROPY);
225  d->flag[k][j][i+1] &= ~(FLAG_ENTROPY); ,
226  d->flag[k][j+1][i] &= ~(FLAG_ENTROPY);
227  d->flag[k][j-1][i] &= ~(FLAG_ENTROPY); ,
228  d->flag[k+1][j][i] &= ~(FLAG_ENTROPY);
229  d->flag[k-1][j][i] &= ~(FLAG_ENTROPY);
230  )
231  }
232  #endif
233  }
234 
235  }}}
236 
237  #ifdef PARALLEL
238  AL_Exchange (d->flag[0][0], SZ_char);
239  #endif
240 }
241 
242 #undef EPS_PSHOCK_FLATTEN
243 #undef EPS_PSHOCK_ENTROPY
244 #endif
#define EPS_PSHOCK_FLATTEN
Definition: flag_shock.c:70
#define VX2
Definition: mod_defs.h:29
#define RHO
Definition: mod_defs.h:19
long int NX2_TOT
Total number of zones in the X2 direction (boundaries included) for the local processor.
Definition: globals.h:57
double **** Vc
The main four-index data array used for cell-centered primitive variables.
Definition: structs.h:31
#define SPHERICAL
Definition: pluto.h:36
double * dV
Cell volume.
Definition: structs.h:86
#define ARRAY_3D(nx, ny, nz, type)
Definition: prototypes.h:172
double * dx
Definition: structs.h:83
#define VX1
Definition: mod_defs.h:28
#define KDIR
Definition: pluto.h:195
unsigned char *** flag
Pointer to a 3D array setting useful integration flags that are retrieved during integration.
Definition: structs.h:55
#define EPS_PSHOCK_ENTROPY
Definition: flag_shock.c:74
#define FLAG_MINMOD
Reconstruct using MINMOD limiter.
Definition: pluto.h:179
#define POLAR
Definition: pluto.h:35
#define NX3_MAX
Definition: pluto.h:743
#define MIN(a, b)
Definition: macros.h:104
#define NX2_MAX
Definition: pluto.h:742
#define TOT_LOOP(k, j, i)
Definition: macros.h:44
#define FLAG_ENTROPY
Update pressure using entropy equation.
Definition: pluto.h:182
#define IDIR
Definition: pluto.h:193
int AL_Exchange(void *vbuf, int sz_ptr)
Definition: al_exchange.c:26
Definition: structs.h:78
long int NX3_TOT
Total number of zones in the X3 direction (boundaries included) for the local processor.
Definition: globals.h:59
int j
Definition: analysis.c:2
int k
Definition: analysis.c:2
int SZ_char
Definition: globals.h:28
double * x
Definition: structs.h:80
#define GEOMETRY
Definition: definitions_01.h:4
#define CYLINDRICAL
Definition: pluto.h:34
#define s
PLUTO main header file.
D_EXPAND(tot/[n]=(double) grid[IDIR].np_int_glob;, tot/[n]=(double) grid[JDIR].np_int_glob;, tot/[n]=(double) grid[KDIR].np_int_glob;)
Definition: analysis.c:27
Definition: structs.h:30
int i
Definition: analysis.c:2
#define VX3
Definition: mod_defs.h:30
#define FLAG_HLL
Use HLL Riemann solver.
Definition: pluto.h:181
void FlagShock(const Data *, Grid *)
#define JDIR
Definition: pluto.h:194
#define NX1_MAX
Definition: pluto.h:741
long int NX1_TOT
Total number of zones in the X1 direction (boundaries included) for the local processor.
Definition: globals.h:55
double * A
Right interface area, A[i] = .
Definition: structs.h:87