HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
interppoint.para.c
Go to the documentation of this file.
1 
13 
18 #include "decs.h"
19 
20 #include "para_and_paraenohybrid.h"
21 
22 
24 void parainitchecks(void)
25 {
26  int dimen;
27 
28 
29  DIMENLOOP(dimen){
31  // if PARAMODWENO==1 implied, but if 0 allow since doesn't matter if doing weno with PARAGENDQALLOWEXTREMUM==1
32  // then ok
33  }
34  else if(PARAMODWENO==1 && PARAGENDQALLOWEXTREMUM==0 && WENOINTERPTYPE(lim[dimen])){
35  dualfprintf(fail_file,"WARNING: PARAGENDQALLOWEXTREMUM==0 for hybrid method, will be less accurate for turbulent regions\n");
36  }
37  else if(PARAGENDQALLOWEXTREMUM==1 && lim[dimen]==PARA){
38  dualfprintf(fail_file,"ERROR: PARAGENDQALLOWEXTREMUM==1 but not WENO-based limiter -- will be less stable in stiff regions (e.g. near horizon). Use PARALINE instead.\n");
39  myexit(34643463);
40  }
41 
42  if(lim[dimen]==PARAFLAT){
43  dualfprintf(fail_file,"WARNING: PARAFLAT inefficient compared to PARALINE, suggested to use PARALINE instead\n");
44  }
45  }
46 
47 
48 }
49 
50 
51 
52 
56 void para(FTYPE *y, FTYPE *lout, FTYPE *rout)
57 {
58  int mm ;
59  FTYPE dq0[5];
60  FTYPE *dq;
61  FTYPE Dqm, Dqc, Dqp, aDqm,aDqp,aDqc,s,l,r,qa, qd, qe;
62 
63  // shifted dq
64  dq=dq0+2;
65 
66  /*CW1.7 */
67  for(mm=-1 ; mm<=1 ; mm++) {
68  Dqm = 2.0 *(y[mm]-y[mm-1]);
69  Dqp = 2.0 *(y[mm+1]-y[mm]);
70  Dqc = 0.5 *(y[mm+1]-y[mm-1]);
71  aDqm = fabs(Dqm) ;
72  aDqp = fabs(Dqp) ;
73  aDqc = fabs(Dqc) ;
74  s = Dqm*Dqp;
75 
76  if (s <=0.) dq[mm]=0.; //CW1.8
77  else dq[mm]=min(aDqc,min(aDqm,aDqp))*sign(Dqc);
78  }
79 
80  /* CW1.6 */
81 
82  l=0.5*(y[0]+y[-1])-(dq[0]-dq[-1])/6.0;
83  r=0.5*(y[1]+y[0])-(dq[1]-dq[0])/6.0;
84 
85  qa=(r-y[0])*(y[0]-l);
86  qd=(r-l);
87  qe=6.0*(y[0]-0.5*(l+r));
88 
89 
90  if (qa <=0. ) {
91  l=y[0];
92  r=y[0];
93  }
94 
95  if (qd*(qd-qe)<0.0) l=3.0*y[0]-2.0*r;
96  else if (qd*(qd+qe)<0.0) r=3.0*y[0]-2.0*l;
97 
98 
99  *lout=l; //a_L,j
100  *rout=r;
101  //*dw=r-l; //CW1.5
102  //*w6=6.0*(y[0]-0.5*(l+r));
103 }
104 
105 
106 
108 void para2(FTYPE *y, FTYPE *lout, FTYPE *rout)
109 {
110  int mm ;
111  FTYPE dq0[5];
112  FTYPE *dq;
113  FTYPE Dqm, Dqc, Dqp, Dqvanl,aDqm,aDqp,aDqc,aDqvanl,s,l,r,qa, qd, qe;
114 
115  // shifted dq
116  dq=dq0+2;
117 
118  /*CW1.7 */
119  for(mm=-1 ; mm<=1 ; mm++) {
120  Dqm = 2.0 *(y[mm]-y[mm-1]);
121  Dqp = 2.0 *(y[mm+1]-y[mm]);
122  Dqc = 0.5 *(y[mm+1]-y[mm-1]);
123  aDqm = fabs(Dqm) ;
124  aDqp = fabs(Dqp) ;
125  aDqc = fabs(Dqc) ;
126  s = Dqm*Dqp;
127 
128 #if(PARA2LIM == VANL)
129  Dqvanl=2.0*Dqm*Dqp/(Dqm+Dqp);
130  aDqvanl=fabs(Dqvanl);
131  if (s <=0.) dq[mm]=0.; //CW1.8
132  else dq[mm]=min(min(aDqc,aDqvanl),min(aDqm,aDqp))*sign(Dqc);
133 #elif(PARA2LIM == PMC)
134  if (s <=0.) dq[mm]=0.; //CW1.8
135  else dq[mm]=min(aDqc,min(aDqm,aDqp))*sign(Dqc);
136 #elif(PARA2LIM == MC)
137  dq[mm] =Dqc;
138 #endif
139  }
140  /* CW1.6 */
141 
142  l=0.5*(y[0]+y[-1])-(dq[0]-dq[-1])/6.0;
143  r=0.5*(y[1]+y[0])-(dq[1]-dq[0])/6.0;
144 
145  /*
146  l=max(min(y[0],y[-1]),l);
147  l=min(max(y[0],y[-1]),l);
148  r=max(min(y[0],y[1]),r);
149  r=min(max(y[0],y[1]),r);
150  */
151 
152  qa=(r-y[0])*(y[0]-l);
153  qd=(r-l);
154  qe=6.0*(y[0]-0.5*(l+r));
155 
156 
157  if (qa <=0. ) {
158  l=y[0];
159  r=y[0];
160  }
161 
162  else if (qd*(qd-qe)<0.0) l=3.0*y[0]-2.0*r;
163  else if (qd*(qd+qe)<0.0) r=3.0*y[0]-2.0*l;
164 
165 
166  *lout=l; //a_L,j
167  *rout=r;
168  //*dw=r-l; //CW1.5
169  //*w6=6.0*(y[0]-0.5*(l+r));
170 }
171 
172 
173 
174 
177 void para3(FTYPE *y, FTYPE *lout, FTYPE *rout)
178 {
179  int mm ;
180  FTYPE dq0[5];
181  FTYPE *dq;
182  FTYPE Dqm, Dqc, Dqp, Dqvanl,aDqm,aDqp,aDqc,aDqvanl,s,l,r,qa, qd, qe;
183 
184  // shifted dq
185  dq=dq0+2;
186 
187  /*CW1.7 */
188  for(mm=-1 ; mm<=1 ; mm++) {
189  Dqm = 2.0 *(y[mm]-y[mm-1]);
190  Dqp = 2.0 *(y[mm+1]-y[mm]);
191  Dqc = 0.5 *(y[mm+1]-y[mm-1]);
192  aDqm = fabs(Dqm) ;
193  aDqp = fabs(Dqp) ;
194  aDqc = fabs(Dqc) ;
195  s = Dqm*Dqp;
196 
197 #if(PARA2LIM == VANL)
198  Dqvanl=2.0*Dqm*Dqp/(Dqm+Dqp);
199  aDqvanl=fabs(Dqvanl);
200 
201  if (s <=0.) dq[mm]=0.;
202  else dq[mm] = -aDqvanl*sign(Dqc);
203  //else dq[mm]=min(min(aDqc,aDqvanl),min(aDqm,aDqp))*sign(Dqc);
204 #elif(PARA2LIM == MC)
205  if (s <=0.) dq[mm]=0.; //CW1.8
206  else dq[mm]=-min(aDqc,min(aDqm,aDqp))*sign(Dqc);
207 #elif(PARA2LIM == MINM)
208  if (s<=0.) dq[mm] = 0.;
209  else if (aDqm<aDqp) dq[mm] = -aDqm*sign(Dqc);
210  else dq[mm]=-aDqp*sign(Dqc);
211 #elif(PARA2LIM == NLIM) //w/o slope limiter
212  //if(s<=0.) dq[mm] = 0.; // DONOR
213  dq[mm] = Dqc;
214 #endif
215  }
216 
217  /* CW1.6 */
218 
219  l=0.5*(y[0]+y[-1])-(dq[0]-dq[-1])/6.0;
220  r=0.5*(y[1]+y[0])-(dq[1]-dq[0])/6.0;
221 
222 
223  l=max(min(y[0],y[-1]),l);
224  l=min(max(y[0],y[-1]),l);
225  r=max(min(y[0],y[1]),r);
226  r=min(max(y[0],y[1]),r);
227 
228 
229  qa=(r-y[0])*(y[0]-l);
230  qd=(r-l);
231  qe=6.0*(y[0]-0.5*(l+r));
232 
233  /*
234  if (qa <=0. ) {
235  l=y[0];
236  r=y[0];
237  }
238 
239  else if (qd*(qd-qe)<0.0) l=3.0*y[0]-2.0*r;
240  else if (qd*(qd+qe)<0.0) r=3.0*y[0]-2.0*l;
241 
242 
243  *lout=l; //a_L,j
244  *rout=r;
245  */
246 
247  if (qa <=0. ) {
248  *lout=y[0];
249  *rout=y[0];
250  }
251  else {
252  *lout = l;
253  *rout = r;
254  }
255 
256  //2.0 at top/bottom of a steep gradient
257  if (qd*(qd-qe)<0.0) *lout=3.0*y[0]-2.0*r;
258  else *lout = l;
259 
260  if (qd*(qd+qe)<0.0) *rout=3.0*y[0]-2.0*l;
261  else *rout = r;
262  //*dw=r-l; //CW1.5
263  //*w6=6.0*(y[0]-0.5*(l+r));
264 }
265 
266 
267 
268 
269 
271 void para4_old(int pl, FTYPE *y, FTYPE *lout, FTYPE *rout)
272 {
273  int mm ;
274  FTYPE dq0[5];
275  FTYPE *dq;
276  FTYPE Dqm, Dqc, Dqp, Dqvanl,aDqm,aDqp,aDqc,aDqvanl,s,l,r,qa, qd, qe;
277  void slope_lim_3points(int reallim, FTYPE yl, FTYPE yc, FTYPE yr,FTYPE *dq);
278 
279  // shifted dq
280  dq=dq0+2;
281 
282  /*CW1.7 */
283  for(mm=-1 ; mm<=1 ; mm++) {
284  Dqm = 2.0 *(y[mm]-y[mm-1]);
285  Dqp = 2.0 *(y[mm+1]-y[mm]);
286  Dqc = 0.5 *(y[mm+1]-y[mm-1]);
287  aDqm = fabs(Dqm) ;
288  aDqp = fabs(Dqp) ;
289  aDqc = fabs(Dqc) ;
290  s = Dqm*Dqp;
291 
292 
293 #if(PARA2LIM == VANL)
294  Dqvanl=2.0*Dqm*Dqp/(Dqm+Dqp);
295  aDqvanl=fabs(Dqvanl);
296 
297  if (s <=0.) dq[mm]=0.;
298  //else dq[mm] = aDqvanl*sign(Dqc);
299  else dq[mm]=min(min(aDqc,aDqvanl),min(aDqm,aDqp))*sign(Dqc);
300 
301 #elif(PARA2LIM == MC)
302 
303 #if(0)
304  // Jon's version
305  dq[mm]=MINMOD(Dqc,MINMOD(Dqm,Dqp));
306 #else
307  // Xioyue's version
308  if (s <=0.) dq[mm]=0.; //CW1.8
309  else dq[mm]= min(aDqc,min(aDqm,aDqp))*sign(Dqc);
310 #endif
311 
312 
313 
314 #elif(PARA2LIM == MINM_STEEPENER)
315 
316  // Xioyue's version (steepeneed version of MINM)
317  if (s<=0.) dq[mm] = 0.;
318  else if (aDqm<aDqp) dq[mm] = aDqm*sign(Dqc);
319  else dq[mm]=aDqp*sign(Dqc);
320 
321 
322 #elif(PARA2LIM == MINM) // no steepener, normal MINM
323 
324 #if(0)
325  // Jon's version
326  dq[mm] = MINMOD(0.5*Dqm,0.5*Dqp); // no steepening
327 #elif(1)
328  // Jon's steep version
329  if (s<=0.) dq[mm] = 0.;
330  else if (aDqm<aDqp) dq[mm] = aDqm*sign(Dqc);
331  else dq[mm]=aDqp*sign(Dqc);
332 #elif(0)
333  // Xioyue's version
334  if (s<=0.) dq[mm] = 0.;
335  else if (aDqm<aDqp) dq[mm] = 0.5*aDqm*sign(Dqc);
336  else dq[mm]=0.5*aDqp*sign(Dqc);
337 #endif
338 
339 #elif(PARA2LIM == NLIM) //w/o slope limiter
340 
341  dq[mm] = Dqc;
342 #endif
343  }
344 
345 #if(JONPARAREDUCE)
346  // if(pl==U1){
347  if(pl!=RHO){
348  if(
349  (fabs(dq[-1]-dq[0])/(fabs(dq[-1])+fabs(dq[0])+SMALL)>0.1)||
350  (fabs(dq[1]-dq[0])/(fabs(dq[1])+fabs(dq[0])+SMALL)>0.1)
351  ){
352  slope_lim_3points(MINM, y[-1], y[0], y[1], dq);
353  *lout =y[0] - 0.5* (*dq);
354  *rout=y[0] + 0.5* (*dq);
355  return;
356  }
357  }
358 
359 #endif
360 
361  /* CW1.6 */
362 
363  // modified as per Matt's paper
364  l=0.5*(y[0]+y[-1])-(dq[0]-dq[-1])/8.0;
365  r=0.5*(y[1]+y[0])-(dq[1]-dq[0])/8.0;
366 
367 
368  l=max(min(y[0],y[-1]),l);
369  l=min(max(y[0],y[-1]),l);
370  r=max(min(y[0],y[1]),r);
371  r=min(max(y[0],y[1]),r);
372 
373 
374  // modified as per Matt's paper
375  qa=(r-y[0])*(y[0]-l);
376  qd=(r-l);
377  qe=6.0*(y[0]-0.5*(l+r));
378 
379 
380  if (qa <=0. ) {
381  l=y[0];
382  r=y[0];
383  }
384  else{
385 
386  if (qd*(qd-qe)<0.0)
387  l=3.0*y[0]-2.0*r;
388 
389 
390  if (qd*(qd+qe)<0.0)
391  r=3.0*y[0]-2.0*l;
392  }
393 
394 
395  *lout=l; //a_L,j
396  *rout=r;
397 
398  // *dqleft=dq[-1];
399  // *dqcenter=dq[0];
400  // *dqright=dq[1];
401 
402 }
403 
404 
405 #define DO4MONO 0 // whether to add-back-in some trend that one removed -- not working yet in this code
406 
407 #define OVERRIDEWITHMINM 1
408 
411 void parajon(int ii, int jj, int kk, int loc, int realisinterp, int dir, int pl, FTYPE *y, FTYPE *lout, FTYPE *rout)
412 {
413  int mm;
414  FTYPE dq0[10];
415  FTYPE *dq;
416  FTYPE Dqm, Dqc, Dqp, Dqvanl,aDqm,aDqp,aDqc,aDqvanl,s,l,r,qa, qd, qe;
417  void slope_lim_3points(int reallim, FTYPE yl, FTYPE yc, FTYPE yr,FTYPE *dq);
418  void jonparasmooth_compute(int realisinterp, int dqrange, int pl, FTYPE *y, FTYPE *dq1, FTYPE *dq2, FTYPE *lout, FTYPE *rout, int *smooth);
419  int smooth=0;
420  int a_whichdq[10];
421  FTYPE a_y4mono[10];
422  FTYPE *y4mono;
423  int *whichdq;
424  int dqrange=2;
425  int usepara;
426  FTYPE s0;
427  int iii,jjj,kkk;
428  FTYPE Dqm4mono,Dqc4mono,Dqp4mono;
429  FTYPE s4mono;
430  FTYPE aDqm4mono,aDqc4mono,aDqp4mono;
431 
432  int shifti=(dir==1);
433  int shiftj=(dir==2);
434  int shiftk=(dir==3);
435 
436 
437  // shifted dq
438  dq=dq0+dqrange;
439  whichdq=a_whichdq+dqrange;
440 
441 #if(DO4MONO)
442  y4mono=a_y4mono+dqrange;
443 
444  // get true function
445  for(mm=-2 ; mm<=2 ; mm++) {
446  iii=ii+shifti*mm;
447  jjj=jj+shiftj*mm;
448  kkk=kk+shiftk*mm;
449 
450  y4mono[mm] = y[mm]*GLOBALMACP1A0(pother,RHOCENTA+pl,iii,jjj,kkk);
451  }
452 #endif
453 
454 
455  /*CW1.7 */
456  s0=1.0;
457  for(mm=-1 ; mm<=1 ; mm++) {
458  Dqm = 2.0 *(y[mm]-y[mm-1]);
459  Dqp = 2.0 *(y[mm+1]-y[mm]);
460  Dqc = 0.5 *(y[mm+1]-y[mm-1]);
461 
462 
463 #if(DO4MONO)
464  // 4mono version
465  Dqm4mono = 2.0 *(y4mono[mm]-y4mono[mm-1]);
466  Dqp4mono = 2.0 *(y4mono[mm+1]-y4mono[mm]);
467  Dqc4mono = 0.5 *(y4mono[mm+1]-y4mono[mm-1]);
468 #else
469  // normal version
470  Dqm4mono = Dqm;
471  Dqp4mono = Dqp;
472  Dqc4mono = Dqc;
473 #endif
474 
475 
476  // check what slope is chosen
477  if(fabs(Dqc4mono)<=fabs(Dqm4mono) && fabs(Dqc4mono)<=fabs(Dqp4mono)){
478  // central picked .. is fine
479  whichdq[mm]=0;
480  }
481  else if(fabs(Dqm4mono)<=fabs(Dqp4mono) && fabs(Dqm4mono)<=fabs(Dqc4mono)){
482  // check if really want to steepen
483  whichdq[mm]=-1;
484  }
485  else if(fabs(Dqp4mono)<=fabs(Dqm4mono) && fabs(Dqp4mono)<=fabs(Dqc4mono)){
486  whichdq[mm]=+1;
487  }
488  else{
489  whichdq[mm]=+1; // GODMARK: Shouldn't really get here
490  }
491 
492 
493 
494 
495  aDqm = fabs(Dqm) ;
496  aDqp = fabs(Dqp) ;
497  aDqc = fabs(Dqc) ;
498  s = Dqm*Dqp;
499 
500  aDqm4mono = fabs(Dqm4mono) ;
501  aDqp4mono = fabs(Dqp4mono) ;
502  aDqc4mono = fabs(Dqc4mono) ;
503 
504  s4mono = Dqm4mono*Dqp4mono;
505  if(s4mono<=0) s0=-1;
506 
507 
508 
509 #if(OVERRIDEWITHMINM || PARA2LIM == MINM) // no steepener, normal MINM
510  // in stiff regime, MINM is more stable than other schemes with steepeners
511  if (s4mono<=0.) dq[mm] = 0.;
512  else if (aDqm4mono<aDqp4mono) dq[mm] = 0.5*Dqm;
513  else dq[mm]=0.5*Dqp;
514 #elif(PARA2LIM == VANL)
515  // NOT DONE for 4mono method
516  Dqvanl=2.0*Dqm*Dqp/(Dqm+Dqp);
517  aDqvanl=fabs(Dqvanl);
518 
519  if (s4mono <=0.) dq[mm]=0.;
520  else dq[mm]=min(min(aDqc,aDqvanl),min(aDqm,aDqp))*sign(Dqc);
521 
522 #elif(PARA2LIM == MC)
523 
524  if (s4mono <=0.) dq[mm]=0.; //CW1.8
525  else if (aDqm4mono<aDqp4mono && aDqm4mono<aDqc4mono) dq[mm] = Dqm;
526  else if (aDqp4mono<aDqm4mono && aDqp4mono<aDqc4mono) dq[mm] = Dqp;
527  else dq[mm]=Dqc;
528 
529 #elif(PARA2LIM == MINM_STEEPENER)
530 
531  // Xioyue's version (steepeneed version of MINM)
532  if (s4mono<=0.) dq[mm] = 0.;
533  else if (aDqm4mono<aDqp4mono) dq[mm] = Dqm;
534  else dq[mm]=Dqp;
535 
536 
537 #elif(PARA2LIM == NLIM) //w/o slope limiter
538  dq[mm] = Dqc;
539 #endif
540  }
541 
542 
543 
544 
545  // no matter what dqrange is, just go from -1..1
546  usepara=0;
547  for(mm=-1 ; mm<=1 ; mm++) {
548  usepara+=(whichdq[mm]==0);
549  }
550 
551  // if(usepara==3 && s0>=0.0){
552  // if(usepara==3 && s0>=0.0 && 0){ // ONLY MINMOD
553  if(usepara==3 && s0>=0.0){
554  // then use interior parabola and be done
555  *lout=(1./8.)*(6.0*y[0]+3.0*y[-1]-y[1]);
556  *rout=(1./8.)*(6.0*y[0]-y[-1]+3.0*y[1]);
557  }
558  else{
559  // then just use 2nd order
560  *lout=y[0]-0.5*dq[0];
561  *rout=y[0]+0.5*dq[0];
562  }
563 
564 
565 }
566 
567 
568 
569 
571 void para4(int realisinterp, int pl, FTYPE *y, FTYPE *lout, FTYPE *rout)
572 {
573  void para4gen(int realisinterp, int dqrange, int pl, FTYPE *y, FTYPE *lout, FTYPE *rout, FTYPE *dq, int *smooth);
574  void checkparamonotonicity(int smooth, int dqrange, int pl, FTYPE *y, FTYPE *ddq, FTYPE *dq, FTYPE *lin, FTYPE *rin, FTYPE *lout, FTYPE *rout);
575  FTYPE dq0[5];
576  FTYPE *dq;
577  int dqrange;
578  FTYPE a_ddq[7];
579  FTYPE *ddq;
580  int mm;
581  int smooth;
582 
583 
584  dqrange=3;
585  // shifted dq
586  dq=dq0+2;
587  ddq=a_ddq+3; // shifted sufficiently
588 
589 
590  para4gen(realisinterp,dqrange, pl,y,lout,rout,dq,&smooth);
591 
592  for(mm=-dqrange/2+1;mm<=dqrange/2;mm++){
593  ddq[mm] = dq[mm] - dq[mm-1];
594  }
595  checkparamonotonicity(smooth, dqrange, pl, y, ddq, dq, lout, rout, lout, rout);
596 
597 
598 }
599 
600 
601 
602 
603 #if(PARAGENDQALLOWEXTREMUM==0)
604 #define PARAGENMINMOD(a,b) MINMOD(a,b)
605 #else
606 #define PARAGENMINMOD(a,b) MINMODB(a,b)
607 #endif
608 
614 void para4gen(int realisinterp, int dqrange, int pl, FTYPE *y, FTYPE *lout, FTYPE *rout, FTYPE *dq, int *smooth)
615 {
616  int mm ;
617  FTYPE a_dq1[10],a_dq2[10];
618  FTYPE *dq1,*dq2;
619  FTYPE Dqm, Dqc, Dqp, Dqvanl,aDqm,aDqp,aDqc,aDqvanl,s,l,r;
620  void slope_lim_3points(int reallim, FTYPE yl, FTYPE yc, FTYPE yr,FTYPE *dq);
621  FTYPE Dqparacenterleft,Dqparacenterright;
622  FTYPE Dqsteep;
623  FTYPE ddql,ddqr;
624  void paracont(FTYPE ddq, FTYPE *y, FTYPE *facecont);
625  void jonparasmooth_compute(int realisinterp, int dqrange, int pl, FTYPE *y, FTYPE *dq1, FTYPE *dq2, FTYPE *lout, FTYPE *rout, int *smooth);
626 
627 
628 
629 
630 
631  // Procedure:
632  // 1) First obtain limited slopes (above)
633  // 2) Assume l,r obtained from 3rd order polynomial for points or quartic for averages
634  // 3) steepen or flatten solution
635  // 4) Check monotonicity:
636  // Condition 1: If y[0] is a local max or local min compared to l,r, then set l=r=y[0]
637  // Condition 2: If parabola fit through l,y[0],r is non-monotonic, then if non-monotonic region is near l, then modify r until derivative of parabola at l is 0.
638 
639  // shifted dq (sufficiently shifted)
640  dq1=a_dq1+dqrange;
641  dq2=a_dq2+dqrange;
642  // setup defaults
643  *smooth=0;
644 
645 
646 
647 #if(JONPARASTEEP)
648 
649  //
650  // first check if 3rd order polynomial will have derivative at center of cell that MC says doesn't need steepening
651  //
653 
654  mm=0;
655  Dqm = 2.0 *(y[mm]-y[mm-1]); // steepened
656  Dqp = 2.0 *(y[mm+1]-y[mm]); // steepened
657  // Dqc = 0.5 *(y[mm+1]-y[mm-1]); // normal
658  // Note that the factors of 3 (and 6) cause asymmetries at roundoff-error
659  Dqparacenterleft = (+0.5*y[0]-y[-1] +y[-2]/6.0+y[1]/3.0); // used to get a_{j-1/2}
660  Dqparacenterright = (-0.5*y[0]-y[-1]/3.0+y[1] - y[2]/6.0); // used to get a_{j+1/2}
661  // see if para will use centered slope that is not steepened enough compared to MC
662 
663  // first compare Dqp and Dqm
664  Dqsteep=PARAGENMINMOD(Dqm,Dqp);
665  // *dq=PARAGENMINMOD(Dqc,PARAGENMINMOD(Dqm,Dqp));
666  // now compare centered with steepened Dqsteep value
667  if(fabs(Dqparacenterleft)>fabs(Dqsteep) && fabs(Dqparacenterright)>fabs(Dqsteep)){
668  *lout = y[0] - 0.5* Dqsteep;
669  *rout = y[0] + 0.5* Dqsteep;
670  //dualfprintf(fail_file,"USEDSTEEP\n");
671  return;
672  // else PARA is ok to use
673  }
674 #endif
675 
676  //dualfprintf(fail_file,"USEDPARA\n");
677 
678 
679 
680 
682  //
683  // get slopes
684  //
686 
687  // Dqm(0) = 2.0*(dq1[0])
688  // Dqp(0) = 2.0*(dq1[1]) // so need to go 1 farther to get all needed Dqp's
689  for(mm=-dqrange/2 ; mm<=dqrange/2 ; mm++) {
690  dq1[mm] = (y[mm]-y[mm-1]); // slope centered at cell face
691  dq2[mm] = 0.5 *(y[mm+1]-y[mm-1]); // slope centered at cell center
692  }
693  mm=dqrange/2+1; // get last dq1 (can't do in loop above since +1 would mean dq2 beyond data range
694  dq1[mm] = (y[mm]-y[mm-1]); // slope centered at cell face
695 
696 
698  //
699  // Determine monotonized slopes
700  //
702 
703  /*CW1.7 */
704  for(mm=-dqrange/2 ; mm<=dqrange/2 ; mm++) {
705 
706  Dqm = 2.0 *dq1[mm]; // steepened
707  Dqp = 2.0 *dq1[mm+1]; // steepened
708  Dqc = dq2[mm]; // normal
709 
710 
711 #if(PARA2LIM == VANL)
712  Dqm*=0.5; // desteepen
713  Dqp*=0.5; // desteepen
714  s = Dqm*Dqp;
715  Dqvanl=2.0*s/(Dqm+Dqp);
716  // aDqvanl=fabs(Dqvanl);
717  // aDqm = fabs(Dqm) ;
718  // aDqp = fabs(Dqp) ;
719  // aDqc = fabs(Dqc) ;
720 
721  // true VANL:
722  if (s <=0.) dq[mm]=0.;
723  else dq[mm] = Dqvanl*sign(Dqc);
724 
725  // Xioyue was using MC-VANL combo of some kind
726  // else dq[mm] = aDqvanl*sign(Dqc);
727  // else dq[mm]=min(min(aDqc,aDqvanl),min(aDqm,aDqp))*sign(Dqc);
728 
729 #elif(PARA2LIM == MC)
730 
731 #if(1)
732  // Jon's version
733  dq[mm]=PARAGENMINMOD(Dqc,PARAGENMINMOD(Dqm,Dqp));
734 #else
735  // Xioyue's version
736  s = Dqm*Dqp;
737  aDqm = fabs(Dqm) ;
738  aDqp = fabs(Dqp) ;
739  aDqc = fabs(Dqc) ;
740  if (s <=0.) dq[mm]=0.; //CW1.8
741  else dq[mm]= min(aDqc,min(aDqm,aDqp))*sign(Dqc);
742 #endif
743 
744 
745 
746 #elif(PARA2LIM == MINM_STEEPENER)
747 
748  // Xioyue's version (steepeneed version of MINM)
749  s = Dqm*Dqp;
750  aDqm = fabs(Dqm) ;
751  aDqp = fabs(Dqp) ;
752  aDqc = fabs(Dqc) ;
753  if (s<=0.) dq[mm] = 0.;
754  else if (aDqm<aDqp) dq[mm] = aDqm*sign(Dqc);
755  else dq[mm]=aDqp*sign(Dqc);
756 
757 
758 #elif(PARA2LIM == MINM) // no steepener, normal MINM
759 
760 #if(1)
761  // Jon's version
762  dq[mm] = PARAGENMINMOD(0.5*Dqm,0.5*Dqp); // no steepening
763 #elif(0)
764  // Jon's steep version
765  s = Dqm*Dqp;
766  aDqm = fabs(Dqm) ;
767  aDqp = fabs(Dqp) ;
768  aDqc = fabs(Dqc) ;
769  if (s<=0.) dq[mm] = 0.;
770  else if (aDqm<aDqp) dq[mm] = aDqm*sign(Dqc);
771  else dq[mm]=aDqp*sign(Dqc);
772 #elif(0)
773  // Xioyue's version
774  s = Dqm*Dqp;
775  aDqm = fabs(Dqm) ;
776  aDqp = fabs(Dqp) ;
777  aDqc = fabs(Dqc) ;
778  if (s<=0.) dq[mm] = 0.;
779  else if (aDqm<aDqp) dq[mm] = 0.5*aDqm*sign(Dqc);
780  else dq[mm]=0.5*aDqp*sign(Dqc);
781 #endif
782 
783 #elif(PARA2LIM == NLIM) //w/o slope limiter
784 
785  dq[mm] = Dqc;
786 #endif
787  }// end loop over mm's
788 
789 
790 
791 
792 #if(JONPARASMOOTH)
793  jonparasmooth_compute(realisinterp,dqrange,pl,y,dq1,dq2,lout,rout,smooth);
794  if(*smooth) return;
795 #else
796  *smooth=0;
797 #endif
798 
799 
800 
801 
802 
803 
804 
805 #if(JONPARAREDUCE)
806  // if(pl==U1){
807  if(pl!=RHO){
808  if(
809  (fabs(dq[-1]-dq[0])/(fabs(dq[-1])+fabs(dq[0])+SMALL)>0.1)||
810  (fabs(dq[1]-dq[0])/(fabs(dq[1])+fabs(dq[0])+SMALL)>0.1)
811  ){
812  slope_lim_3points(MINM, y[-1], y[0], y[1], dq);
813  *lout =y[0] - 0.5* (*dq);
814  *rout=y[0] + 0.5* (*dq);
815  return;
816  }
817  }
818 
819 #endif
820 
821 
822 
823 #if(WHICHLIMITERTOUSEFORLR==0)
824 
825  //
826  // Obtain continuous solution at interface
827  //
828  // CW1.6 for obtaining a_{j+1/2} using quartic polynomial, but slopes have been replaced with limited slopes
829  //
830  // GODMARK: This step could be done once for entire line of data
831 
832  ddql=(dq[0]-dq[-1]);
833  ddqr=(dq[1]-dq[0]);
834 
835  paracont(ddql, &y[0], &l);
836  paracont(ddqr, &y[1], &r);
837 
838 
839 
840 
841 
842 #if(0)
843  // doesn't seem to be within CW!
844  l=max(min(y[0],y[-1]),l);
845  l=min(max(y[0],y[-1]),l);
846  r=max(min(y[0],y[1]),r);
847  r=min(max(y[0],y[1]),r);
848 #endif
849 
850  *lout = l;
851  *rout = r;
852 
853 
854 
855 #elif(WHICHLIMITERTOUSEFORLR==1)
856 
857 
858  // notice that this results in discontinuous solution at each interface already, unlike para method
859  *lout = y[0] - 0.5*dq[0];
860  *rout = y[0] + 0.5*dq[0];
861 
862  // differs from normal MC,MINM, etc. by computing dq's that will be used later for steepener, fattener, and parabolic check
863 
864  // Note that MC is actually 3rd order acccurate (error term O(dx^3)) because linear l,r gives same answer as parabola!
865 
866 
867 #endif
868 
869 
870 
871 
872 
873 }
874 
875 
876 
877 
881 void jonparasmooth_compute(int realisinterp, int dqrange, int pl, FTYPE *y, FTYPE *dq1, FTYPE *dq2, FTYPE *lout, FTYPE *rout, int *smooth)
882 {
883  int usepara=0;
884  int mm;
885  FTYPE Dqm,Dqp,Dqc;
886  int a_whichdq[10];
887  int *whichdq;
888 
889 
890  whichdq=a_whichdq+dqrange;
891 
892 
893  for(mm=-dqrange/2 ; mm<=dqrange/2 ; mm++) {
894 
895  Dqm = 2.0 *dq1[mm]; // steepened
896  Dqp = 2.0 *dq1[mm+1]; // steepened
897  Dqc = dq2[mm]; // normal
898 
899  if(fabs(Dqc)<=fabs(Dqm) && fabs(Dqc)<=fabs(Dqp)){
900  // central picked .. is fine
901  whichdq[mm]=0;
902  }
903  else if(fabs(Dqm)<=fabs(Dqp) && fabs(Dqm)<=fabs(Dqc)){
904  // check if really want to steepen
905  whichdq[mm]=-1;
906  }
907  else if(fabs(Dqp)<=fabs(Dqm) && fabs(Dqp)<=fabs(Dqc)){
908  whichdq[mm]=+1;
909  }
910  else{
911  whichdq[mm]=+1; // GODMARK: Shouldn't really get here
912  }
913  }
914 
915 
916  if(realisinterp==1 && pl==RHO && dqrange>=5){
917  // check steepened slopes to ensure really want to steepen
918  // for(mm=-dqrange/2+1 ; mm<=dqrange/2-1 ; mm++) {
919  for(mm=-2 ; mm<=2 ; mm++) {
920  usepara+=(whichdq[mm]==0);
921  }
922 
923  if(usepara==5){
924  // then use interior parabola and be done
925  *lout=(1./8.)*(6.0*y[0]+3.0*y[-1]-y[1]);
926  *rout=(1./8.)*(6.0*y[0]-y[-1]+3.0*y[1]);
927 
928  *smooth=1;
929  return;
930  }
931  // else use para as normal
932  }
933  else{
934  // check steepened slopes to ensure really want to steepen
935  // for(mm=-dqrange/2+1 ; mm<=dqrange/2-1 ; mm++) {
936  for(mm=-1 ; mm<=1 ; mm++) {
937  usepara+=(whichdq[mm]==0);
938  }
939 
940  if(usepara==3){
941  // then use interior parabola and be done
942  *lout=(1./8.)*(6.0*y[0]+3.0*y[-1]-y[1]);
943  *rout=(1./8.)*(6.0*y[0]-y[-1]+3.0*y[1]);
944 
945  *smooth=1;
946  return;
947  }
948  // else use para as normal
949  }
950 
951  *smooth=0;
952 
953 }
954 
955 
956 
957 
958 
959 
961 void paracont(FTYPE ddq, FTYPE *y, FTYPE *facecont)
962 {
963  FTYPE avgpointcoef;
964 
965 
966 #if(AVGINPUT)
967  // /6 is result of passing through points from differential of average values in each cell
968  avgpointcoef=1.0/6.0;
969  *facecont=0.5*(y[0]+y[-1])-ddq*avgpointcoef;
970 #else
971  avgpointcoef=1.0/8.0;
972  // consistent with Matt's paper
973  // assume passing quartic polynomial through points y[-2,-1,0,1,2]
974  // see PARA_interpolation_checks.nb
975  *facecont=0.5*(y[0]+y[-1])-ddq*avgpointcoef;
976 #endif
977 
978 }
979 
980 
981 
982 
985 void paracontsmooth(int pl, FTYPE *y, FTYPE *facecont, int *smooth)
986 {
987  FTYPE ddqtest[4];
988  int whichmax;
989  FTYPE maxddq;
990  FTYPE qc,qd,qe;
991  int i;
992 
993 #if(AVGINPUT)
994  dualfprintf(fail_file,"NOT SETUP\n");
995  myexit(249678346);
996 #else
997  // PARAFLAT has enough points for this
998  ddqtest[0]=y[-1]-2*y[-2]+y[-3];
999  ddqtest[1]=y[0]-2*y[-1]+y[-2];
1000  ddqtest[2]=y[1]-2*y[0]+y[-1];
1001  ddqtest[3]=y[2]-2*y[1]+y[0];
1002  *smooth=0;
1003 
1004  // get biggest ddq
1005  maxddq=0.0;
1006  for(i=0;i<=3;i++){
1007  if(fabs(ddqtest[i])>maxddq){
1008  maxddq=ddqtest[i];
1009  whichmax=i;
1010  }
1011  }
1012 
1013  // normalize ddq's
1014  for(i=0;i<=3;i++){
1015  ddqtest[i]=ddqtest[i]/maxddq; // Then 1.0 will be that ddq that is max
1016  }
1017 
1018  // value of ddq should be same as largest ddq within some percent error
1019 
1020  *smooth=1;
1021  for(i=0;i<=3;i++){
1022  if(ddqtest[i]<-0.1) *smooth=0;
1023  }
1024 
1025  if(pl==U1){
1026  if(!*smooth){
1027  dualfprintf(fail_file,"NOTSMOOTH\n");
1028  for(i=0;i<=3;i++) dualfprintf(fail_file,"ddqtest[%d]=%g maxddq=%g whichmax=%d\n",i,ddqtest[i],maxddq,whichmax);
1029  }
1030  }
1031 
1032 
1033  // if( (sign(ddqtest[0])==sign(ddqtest[1]) && sign(ddqtest[1])==sign(ddqtest[2]) && sign(ddqtest[2])==sign(ddqtest[3])){
1034 
1035  // always compute in case used later regardless of smoothness measurement
1036  *facecont = (1./16.)*(9.*y[0]+9*y[-1]-y[-2]-y[1]);
1037  // *smooth=1;
1038  //}
1039 
1040 #if(0)
1041  if(sign(ddqtest[0])==sign(ddqtest[1]) && sign(ddqtest[1])==sign(ddqtest[2]) && sign(ddqtest[2])==sign(ddqtest[3])){
1042  if(pl==2){
1043  dualfprintf(fail_file,"GOOD :: %g %g %g %g :: %d %d %d\n",
1044  sign(ddqtest[0]),sign(ddqtest[1]),sign(ddqtest[2]),sign(ddqtest[3])
1045  ,sign(ddqtest[0])==sign(ddqtest[1]),sign(ddqtest[1])==sign(ddqtest[2]),sign(ddqtest[2])==sign(ddqtest[3])
1046  );
1047  }
1048  }
1049  else{
1050  if(pl==2){
1051  dualfprintf(fail_file,"BAD::: %g %g %g %g :: %d %d %d\n",
1052  sign(ddqtest[0]),sign(ddqtest[1]),sign(ddqtest[2]),sign(ddqtest[3])
1053  ,sign(ddqtest[0])==sign(ddqtest[1]),sign(ddqtest[1])==sign(ddqtest[2]),sign(ddqtest[2])==sign(ddqtest[3])
1054  );
1055  }
1056  }
1057 #endif
1058 
1059 
1060 
1061 
1062 #endif
1063 
1064 
1065 
1066 }
1067 
1068 
1069 
1070 
1072 void checkparamonotonicity(int smooth, int dqrange, int pl, FTYPE *y, FTYPE *ddq, FTYPE *dq, FTYPE *lin, FTYPE *rin, FTYPE *lout, FTYPE *rout)
1073 {
1074  FTYPE a6COEF;
1075  FTYPE qa,qb,qd,qe;
1076  FTYPE r,l;
1077  int i;
1078  int numddq;
1079 
1080 
1081 
1082 
1083 
1084  l = *lin;
1085  r = *rin;
1086 
1087 
1088 #if(PARAGENDQALLOWEXTREMUM)
1089 
1090  if(smooth) qb=1;
1091  else{
1092  // (dq[0]-dq[-1]) is defined as ddq[0]
1093  // ddqr=(dq[1]-dq[0]) is ddq[1]
1094  qb=0.0;
1095  numddq=0;
1096  for(i=-dqrange/2+1;i<=dqrange/2;i++){
1097  qb+=sign(ddq[i]);
1098  numddq++;
1099  }
1100  // check that ddq's all same sign
1101  if(fabs(qb)>(FTYPE)numddq-0.1) qb=1.0; // 0.1 is just to avoid machine precision issue
1102  else qb=-1.0;
1103  }
1104 #else
1105  if (smooth){
1106  *lout=*lin;
1107  *rout=*rin;
1108  return;
1109  }
1110 #endif
1111 
1112 
1114  //
1115  // now perform the limiting procedures that create the discontinuities
1116 
1117  // Condition 1: monotonicity for l,y[0],r. qa>0 if monotonic
1118  qa=(r-y[0])*(y[0]-l);
1119  // modify Condition 1 as in Duez et al. (2005)
1120  // allow nonmonotonic behavior if the second derivative doesn't change sign around the center
1121  // GODMARK: actually should check 2 derivatives in each direction! Then need PARAFLAT for extra values
1122 
1123 
1124  // CW: \delta a_j
1125  qd=(r-l);
1126 
1127 #if(AVGINPUT)
1128  // CW: a_{6,j} in CW, which is for averages:
1129  a6COEF=6.0;
1130  qe=a6COEF*(y[0]-0.5*(l+r));
1131 #else
1132  // for points need: see PARA_interpolation_checks.nb
1133  // parabola has solution y = l + (x-xl)*(qd + a6*(1-(x-xl))) with a6 = 4(y_0-1/2(l+r)) for points
1134  a6COEF=4.0;
1135  qe=a6COEF*(y[0]-0.5*(l+r));
1136 #endif
1137 
1138 
1139 
1140 
1141 
1142 #if(PARAGENDQALLOWEXTREMUM)
1143  if (qa <=0.0 && qb<=0.0 )
1144 #else
1145  if (qa <=0.0)
1146 #endif
1147  { // Condition 1
1148 
1149 
1150 #if(NONMONOLIM==0)
1151  l=y[0];
1152  r=y[0];
1153 #elif(NONMONOLIM==1)
1154  // makes no sense to reduce all the way to DONOR since to second order can still have monotonic result, so use MONO result in this case and assume flatten result
1155  // appears to be too speculative as results in more failures at horizon with PARA2LIM==MC
1156  l = y[0] - 0.5* dq[0];
1157  r = y[0] + 0.5* dq[0];
1158 #endif
1159 
1160  }
1161  else if(1){
1162  // Condition 2
1163 
1164  // qe can be positive or negative still here even though qa>0
1165  if (qd*(qd-qe)<0.0) l = (-(2.0+a6COEF)*r + 2.0*a6COEF*y[0])/(a6COEF-2.0);
1166  else if(qd*(qd+qe)<0.0) r = (-(2.0+a6COEF)*l + 2.0*a6COEF*y[0])/(a6COEF-2.0);
1167  // else no change needed
1168  // else{
1169  // dualfprintf(fail_file,"Problem with limiting condition 2\n");
1170  // }
1171 
1172  // Xiaoyue's verison:
1173  // if (qd*(qd-qe)<0.0) l=3.0*y[0]-2.0*r;
1174  // if (qd*(qd+qe)<0.0) r=3.0*y[0]-2.0*l;
1175  }
1176 
1177 
1178 #if(PARAGENDQALLOWEXTREMUM)
1179  // recompute monotonicity to confirm didn't screw it up:
1180  qa=(r-y[0])*(y[0]-l);
1181  // qb is not changed!
1182  if (qa <=0. && qb<=0.0 ) { // Condition 1 again
1183  // with Duez allowance of non-monotonic behavior, this gets triggered if l,r change -- otherwise wouldn't have been triggered
1184  l=y[0];
1185  r=y[0];
1186  }
1187 #endif
1188 
1189 
1190  // assign output
1191  *lout=l;
1192  *rout=r;
1193 
1194 
1195 
1196 }
1197 
1198 
1199 
1200 
1201 
1202 
1203 
1205 void parapl(int i, int j, int k, int loc, int realisinterp, int dir, FTYPE **yrealpl, FTYPE **ypl, FTYPE *loutpl, FTYPE *routpl)
1206 {
1207  FTYPE dq0[NPR2INTERP][8];
1208  FTYPE *dq[NPR2INTERP];
1209  FTYPE *y,*yreal;
1210  void parasteep(int dir, int pl, FTYPE *V, FTYPE *P, FTYPE *y, FTYPE *dq, FTYPE *l, FTYPE *r);
1211  void paraflatten(int dir, int pl, FTYPE *y, FTYPE Fi, FTYPE *l, FTYPE *r);
1212  void getPressure(int whicheom, int i, int j, int k, int loc, FTYPE **yrealpl, FTYPE *P);
1213  FTYPE a_P[NUMTRUEEOMSETS][10];
1215  FTYPE Ficalc(int dir, FTYPE *V, FTYPE *P);
1216  int pl,pliter;
1217  FTYPE Fi[NUMTRUEEOMSETS];
1218  int dqrange;
1219  FTYPE a_ddq[7];
1220  FTYPE *ddq;
1221  int mm;
1222  int smooth;
1223  int whicheom;
1224 
1225 
1226 
1227  // consistent with PARAFLAT using 7 points
1228  dqrange = 5; // dq's will exist from -2,-1,0,1,2 and ddq computed from -2,-1,0,1
1229 
1230  // shift P
1231  for(whicheom=0;whicheom<NUMTRUEEOMSETS;whicheom++){
1232  P[whicheom]=a_P[whicheom] + 4; // P accessed from -3..3 ( shifted sufficiently)
1233  }
1234 
1235  // shift dq
1236  PINTERPLOOP(pliter,pl){
1237  dq[pl]=dq0[pl]+4; // shifted sufficiently
1238  }
1239 
1240  ddq=a_ddq+3; // shifted sufficiently
1241 
1242 
1243  // assume velocity is istelf
1244  // KORALTODO: need Ficalc for radiation by itself!
1245  V[EOMSETMHD] = yrealpl[U1+dir-1];
1246 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE)
1247  V[EOMSETRAD] = yrealpl[URAD1+dir-1];
1248 #endif
1249 
1250 
1251  // get pressures for all points since needed for reduction or steepening
1252 #if( DOPPMREDUCE || DOPPMCONTACTSTEEP)
1253  for(whicheom=0;whicheom<NUMTRUEEOMSETS;whicheom++){
1254  if(whicheom==EOMSETRAD && RADSHOCKFLAT || whicheom==EOMSETMHD) getPressure(whicheom,i, j, k, loc, yrealpl, P[whicheom]);
1255  }
1256 #endif
1257 
1258 
1259 
1260  // computed only once for all variables
1261  for(whicheom=0;whicheom<NUMTRUEEOMSETS;whicheom++){
1262  if(whicheom==EOMSETRAD && RADSHOCKFLAT || whicheom==EOMSETMHD){
1263 #if( DOPPMREDUCE )
1264  Fi[whicheom] = Ficalc(dir,V[whicheom],P[whicheom]);
1265 #else
1266  Fi[whicheom] = 0.0;
1267 #endif
1268  }
1269  }
1270 
1271 
1273  //
1274  // Loop over variables and get interpolated left/right values within cell
1275  //
1277 
1278 
1279  PINTERPLOOP(pliter,pl){
1280 
1281  y=ypl[pl];
1282  yreal=yrealpl[pl];
1283 
1284  // get continuous solution
1285  para4gen(realisinterp,dqrange,pl,y,&loutpl[pl],&routpl[pl],dq[pl],&smooth);
1286 
1287 #if(DOPPMCONTACTSTEEP)
1288  if(RADFULLPL(pl)&&RADSHOCKFLAT) parasteep(dir,pl,V[EOMSETRAD],P[EOMSETRAD],ypl[pl],dq[pl],&loutpl[pl],&routpl[pl]);
1289  if(!RADFULLPL(pl)) parasteep(dir,pl,V[EOMSETMHD],P[EOMSETMHD],ypl[pl],dq[pl],&loutpl[pl],&routpl[pl]);
1290 #endif
1291 
1292 
1293 #if( DOPPMREDUCE )
1294  if(RADFULLPL(pl)&&RADSHOCKFLAT) paraflatten(dir,pl,ypl[pl],Fi[EOMSETRAD],&loutpl[pl],&routpl[pl]);
1295  if(!RADFULLPL(pl)) paraflatten(dir,pl,ypl[pl],Fi[EOMSETMHD],&loutpl[pl],&routpl[pl]);
1296 #endif
1297 
1298 
1299  // finally check monotonicity of the parabola and create discontinuities if non-monotonic
1300  // FLASH equations 51 -> 53 for points or averages
1301  for(mm=-dqrange/2+1;mm<=dqrange/2;mm++){
1302  ddq[mm] = dq[pl][mm] - dq[pl][mm-1];
1303  }
1304  checkparamonotonicity(smooth, dqrange, pl, ypl[pl], ddq, dq[pl], &loutpl[pl], &routpl[pl], &loutpl[pl], &routpl[pl]);
1305 
1306 #if(NONMONOLIM>0 && DOPPMREDUCE)
1307  // then flatten again
1308  if(RADFULLPL(pl)&&RADSHOCKFLAT) paraflatten(dir,pl,ypl[pl],Fi[EOMSETRAD],&loutpl[pl],&routpl[pl]);
1309  if(!RADFULLPL(pl)) paraflatten(dir,pl,ypl[pl],Fi[EOMSETMHD],&loutpl[pl],&routpl[pl]);
1310 #endif
1311 
1312 
1313  }
1314 
1315 
1316 
1317 }
1318 
1319 
1320 
1322 void paraflatten(int dir, int pl, FTYPE *y, FTYPE Fi, FTYPE *l, FTYPE *r)
1323 {
1324  // FLASH Equation 49,50
1325  *l = Fi * y[0] + ( 1.0 - Fi ) * (*l);
1326  *r = Fi * y[0] + ( 1.0 - Fi ) * (*r);
1327 }
1328 
1329 
1330 
1331 
1333 FTYPE ftilde( int dir, int shift, FTYPE *Vabs, FTYPE *Pabs)
1334 {
1335  FTYPE Ftilde,Ftilde1,Ftilde2;
1336  FTYPE Sp;
1337  FTYPE *V, *P;
1338  FTYPE P2diff,Pbottom;
1339 
1340 
1341  // shift as needed
1342  P = Pabs + shift;
1343  V = Vabs + shift;
1344 
1345  // FLASH Equation 43 (pressure jump)
1346  P2diff=P[2]-P[-2];
1347  Pbottom=sign(P2diff)/(fabs(P2diff)+SMALL); // singularity avoidance but keeps signature
1348  Sp = (P[1] - P[-1]) * Pbottom ;
1349 
1350 
1351 
1352 
1353  // FLASH Equation 45 (shock must have sufficient pressure jump)
1354  Ftilde = max( 0, min( 1.0, 10.0 * (Sp - SP0) ) );
1355 
1356  // FLASH Equation 46 (shock must have pressure jump)
1357  Ftilde1 = fabs(P[1] - P[-1]) / (min(fabs(P[1]), fabs(P[-1]))+ SMALL );
1358  Ftilde *= ( (FTYPE)(Ftilde1>=THIRD) );
1359  // if(Ftilde1<THIRD) Ftilde=0.0;
1360 
1361  // FLASH Equation 47 (shock must have convergence)
1362  Ftilde2 = V[1] - V[-1];
1363  Ftilde *= ( (FTYPE)(Ftilde2<=0.0) );
1364  // if(Ftilde2>0.0) Ftilde=0.0;
1365 
1366  // dualfprintf(fail_file,"Ftilde=%21.15g\n",Ftilde);
1367 
1368  return( Ftilde );
1369 }
1370 
1371 FTYPE divftilde( int dir, int shift, FTYPE *Vabs, FTYPE *Pabs)
1372 {
1373  FTYPE Ftilde,Ftilde1,Ftilde2;
1374  FTYPE Sv;
1375  FTYPE *V, *P;
1376  FTYPE V2diff,Vbottom;
1377 
1378 
1379  // shift as needed
1380  P = Pabs + shift;
1381  V = Vabs + shift;
1382 
1383  // (flow divergence)
1384  Sv = fabs(V[1] - V[-1]) / ( fabs(V[1]) + fabs(V[-1]) + SMALL );
1385 
1386  // (flow divergence must be sufficient)
1387  Ftilde = MAX(SV0,MIN(+1.0,Sv));
1388 
1389  Ftilde2 = V[1] - V[-1];
1390  Ftilde *= ( (FTYPE)(Ftilde2>=0.0) );
1391 
1392  return( Ftilde );
1393 }
1394 
1395 
1397 FTYPE Ficalc(int dir, FTYPE *V, FTYPE *P)
1398 {
1399  FTYPE ftilde( int dir, int shift, FTYPE *P, FTYPE *V);
1400  int signdP;
1401  FTYPE Fi;
1402 
1403  signdP = (P[1] - P[-1] > 0) * 2 - 1;
1404  // FLASH Equation 48
1405  Fi = max( ftilde(dir, 0, V,P), ftilde(dir, -signdP, V,P) );
1406 
1407  return(Fi);
1408 }
1409 
1412 FTYPE Divcalc(int dir, FTYPE Fi, FTYPE *V, FTYPE *P)
1413 {
1414  FTYPE divftilde( int dir, int shift, FTYPE *Vabs, FTYPE *Pabs);
1415  FTYPE ftilde( int dir, int shift, FTYPE *P, FTYPE *V);
1416  int signdV;
1417  FTYPE Div;
1418 
1419  signdV = (V[1] - V[-1] > 0) * 2 - 1;
1420  Div = max( divftilde(dir, 0, V,P), divftilde(dir, -signdV, V,P) );
1421 
1422  // now put back actual scale
1423  Div *= (V[1] - V[-1]);
1424 
1425  return(Div);
1426 }
1427 
1428 
1429 
1433 void getPressure(int whicheom, int i, int j, int k, int loc, FTYPE **yrealpl, FTYPE *P)
1434 {
1435  int mm;
1436 
1437 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE)
1438  FTYPE tautot[NDIM],tautotmax;
1439  struct of_geom geomdontuse;
1440  struct of_geom *ptrgeom=&geomdontuse;
1441  get_geometry(i,j,k,loc,ptrgeom);
1442  FTYPE prreal[NPR];
1443  int pl;
1444 #endif
1445 
1446  // need pressure over full range from -3..3
1447  for(mm=-interporder[PARAFLAT]/2;mm<=interporder[PARAFLAT]/2;mm++){
1448  P[mm] = 0.0;
1449 
1450  if(whicheom==EOMSETMHD){
1451  P[mm] += pressure_rho0_u_simple(i, j, k, loc, yrealpl[RHO][mm],yrealpl[UU][mm]);
1452  }
1453 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE)
1454  if(whicheom==EOMSETRAD || whicheom==EOMSETMHD){
1455  // add radiation pressure to total pressure if optically thick
1456  PALLREALLOOP(pl) prreal[pl]=yrealpl[pl][mm]; // reorder
1457  // calcfull_tautot(prreal, ptrgeom, tautot, &tautotmax);
1458  calc_tautot(prreal, ptrgeom, NULL, tautot, &tautotmax); // very accurate tautot not necessary, so use Tgas=Trad assumption in opacity
1459 
1460  P[mm] += MIN(tautotmax,1.0)*(4.0/3.0-1.0)*yrealpl[PRAD0][mm]; // KORALNOTE: recall pressure just along diagonal and no velocity in R^\mu_\nu
1461  }
1462 #endif
1463  }
1464 
1465 }
1466 
1467 
1468 
1469 
1470 void parasteep(int dir, int pl, FTYPE *V, FTYPE *P, FTYPE *y, FTYPE *dq, FTYPE *l, FTYPE *r)
1471 {
1472  int odir1,odir2;
1473  void parasteepgen(int pl, FTYPE etai, FTYPE *V, FTYPE *P, FTYPE *y, FTYPE *dq, FTYPE *l, FTYPE *r);
1474  FTYPE etaicalc(int pl, FTYPE *y, FTYPE *V, FTYPE *P);
1475  FTYPE etai;
1476 
1477 
1478 
1479 #if(DOPPMSTEEPVARTYPE==0)
1480  if(pl==RHO)
1481 #elif(DOPPMSTEEPVARTYPE==1)
1482  // define orthogonal directions for field steepening
1483  odir1=dir%3+1;
1484  odir2=(dir+1)%3+1;
1485  if(pl==RHO || pl==B1+odir1-1 || pl==B1+odir2-1)
1486 #endif
1487  {
1488  // get contact indicator
1489  etai=etaicalc(pl,y,V,P);
1490  // get steepend values
1491  parasteepgen(pl, etai, V, P, y, dq, l, r);
1492  }
1493 
1494 
1495 }
1496 
1497 
1498 
1502 void parasteepgen(int pl, FTYPE etai, FTYPE *V, FTYPE *P, FTYPE *y, FTYPE *dq, FTYPE *l, FTYPE *r)
1503 {
1504  void pr_contact_compute(int pl, FTYPE *y, FTYPE *dq, FTYPE *prld, FTYPE *prrd);
1505  FTYPE prld, prrd;
1506  FTYPE l0,r0;
1507  FTYPE lmc,rmc;
1508  FTYPE mceta;
1509 
1510 
1511  // compute anti-disspiative left,right values
1512  pr_contact_compute(pl,y,dq,&prld,&prrd);
1513 
1514  // switch to MC for original l,r states if steepening
1515  mceta=4.0*max( 0.25 - etai,0.0 );
1516 
1517  lmc = y[0] - 0.5*dq[0];
1518  rmc = y[0] + 0.5*dq[0];
1519 
1520  l0 = (*l) * mceta + lmc*(1.0-mceta);
1521  r0 = (*r) * mceta + rmc*(1.0-mceta);
1522 
1523  // assign steepened density value
1524  *l = l0 * ( 1.0 - etai ) + prld*etai;
1525  *r = r0 * ( 1.0 - etai ) + prrd*etai;
1526  // else make no changes to l,r
1527 
1528 
1529 
1530 }
1531 
1532 
1533 
1534 void pr_contact_compute(int pl, FTYPE *y, FTYPE *dq, FTYPE *prld, FTYPE *prrd)
1535 {
1536 
1537  // equation 33 and 34 in FLASH
1538  *prld=y[-1]+0.5*dq[-1];
1539  *prrd=y[+1]-0.5*dq[+1];
1540 
1541 
1542 }
1543 
1547 FTYPE etaicalc(int pl, FTYPE *y, FTYPE *V, FTYPE *P)
1548 {
1549  FTYPE delta2l,delta2r;
1550  FTYPE etatilde;
1551  FTYPE etai;
1552  FTYPE ddcoef;
1553  int ii;
1554  FTYPE Pjump,dB,Bmean;
1555  FTYPE prjumpfactor;
1556  FTYPE ifinf;
1557  FTYPE cs2;
1558  int mm;
1559  int mmstart,mmend;
1560  FTYPE max3P,min3P,min3y;
1561 
1562  // y is accessed from y[-2..2]
1563  // P,dq is accessed via dq[-1,0,1]
1564 
1565 
1566 #if(AVGINPUT)
1567  ddcoef=SIXTH;
1568 #else
1569  ddcoef=1.0/8.0;
1570 #endif
1571 
1572  // equation 35 in FLASH
1573  ii=-1;
1574  delta2l=ddcoef*( (y[ii+1]-y[ii]) - (y[ii] - y[ii-1]) );
1575 
1576  // equation 35 in FLASH
1577  ii=1;
1578  delta2r=ddcoef*( (y[ii+1]-y[ii]) - (y[ii] - y[ii-1]) );
1579 
1580  // equation 36 in FLASH
1581  // sign of denominator is important
1582  // we multiply by conditionall that is 0 or 1
1583  if(fabs(y[1]-y[-1])>SMALL){
1584  etatilde=(-(delta2r-delta2l)/(y[1]-y[-1]));
1585  }
1586  else etatilde=0.0;
1587 
1588  // below can lead to asymmetries
1589  //ifinf = ((FTYPE)(fabs(y[1]-y[-1])<0.5*SMALL)); // inf avoidance
1590  //etatilde=(-(delta2r-delta2l)/(y[1]-y[-1] + ifinf*SMALL));
1591 
1592 
1593 
1595  // Pressure jump
1596  max3P=SMALL;
1597  min3P=BIG;
1598  min3y=BIG;
1599  // for(mm=-2;mm<=2;mm++){
1600  // upwinded extension of check
1601  // if(V[0]>0.0){ mmstart=-2; mmend=1; }
1602  // else if(V[0]<0.0) { mmstart=-1; mmend=2; }
1603  // else { mmstart=-1; mmend=1; }
1604  mmstart=-1; mmend=1;
1605  for(mm=mmstart;mm<=mmend;mm++){
1606  if(mm==0) continue; // when wanting original method
1607  max3P=max(max3P,fabs(P[mm]));
1608  min3P=min(min3P,fabs(P[mm]));
1609  min3y=min(min3y,fabs(y[mm]));
1610  }
1611  min3P+=SMALL;
1612 
1613  // min3y=min(min(fabs(y[-1]),fabs(y[1])),fabs(y[0]));
1614 
1615  //Pjump=fabs(P[1]-P[-1])/(min(fabs(P[1]),fabs(P[-1]))+SMALL);
1616  // need more strict and extensive pressure jump check
1617  Pjump=fabs(max3P - min3P)/min3P;
1618 
1619 
1620 
1621 
1622  // consistently use energy density like term
1623  if(pl>=B1 && pl<=B3){
1624  dB = y[1]-y[-1];
1625  Bmean = 0.5*(y[-1] + y[1]); // mean field
1626  // prp1sq=0.5*y[1]*y[1]*sign(y[1]); // magnetic pressure
1627  // prm1sq=0.5*y[-1]*y[-1]*sign(y[-1]);
1628  prjumpfactor=fabs(dB)/(fabs(Bmean)+fabs(dB)+SMALL);
1629 
1630  // dualfprintf(fail_file,"dB=%21.15g Bmean=%21.15g prjumpfactor=%21.15g\n",dB,Bmean,prjumpfactor);
1631  }
1632  else{
1633  prjumpfactor=fabs(y[1]-y[-1])/min3y;
1634 
1635  // check effective c_s given Pressure leaks into steepened density region
1636  // ensure contributes negligibly to dynamics
1637 
1638  // cs2 = max3P/min3y;
1639 
1640  // want cs2 dt^2/dx^2 << 1 to avoid steepening leading to velocity comparable to whatever Courant condition is limited by
1641 
1642  // relativistic check
1643  // don't change energy per baryon by much
1644  // if pressure is relatively flat
1645  // cs2m1check = (cs2 < 5.0 * fabs(P[-1])/fabs(y[-1]));
1646  // cs20check = (cs2 < 5.0 * fabs(P[0])/fabs(y[0]));
1647  // cs2p1check = (cs2 < 5.0 * fabs(P[1])/fabs(y[1]));
1648  }
1649 
1650 
1651 
1652 
1653  // equation 39 in FLASH (not a shock)
1654  // if( Pjump > 0.1*prjumpfactor) etatilde=0.0;
1655  etatilde *= (FTYPE)( Pjump <= 0.1*prjumpfactor);
1656 
1657 
1658 
1659  // equation 37 in FLASH (to avoid triggering on numerical noise)
1660  // if(prjumpfactor<0.01) etatilde=0.0;
1661  etatilde *= (FTYPE)(prjumpfactor>=0.01);
1662  // etatilde *= (FTYPE)(prjumpfactor>=0.1);
1663 
1664  // equation 38 in FLASH (really a contact)
1665  //if(delta2l*delta2r>0.0) etatilde=0.0;
1666  etatilde *= (FTYPE)(delta2l*delta2r<=0.0);
1667 
1668 
1669 
1670  // equation 40 in FLASH
1671  etai=max(0.0,min(20.0*(etatilde-0.05),1.0));
1672 
1673  return(etai);
1674 
1675 }
1676 
1677 
1678 
1679 
1680 
1681 
1682 
1683 
1684 
1685 
1686 
1687 
1688 
1689 
1690