HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
fixup.c
Go to the documentation of this file.
1 
10 #include "decs.h"
11 
12 
13 static int simple_average(int startpl, int endpl, int i, int j, int k, int doingmhd, PFTYPE (*lpflagfailorig)[NSTORE2][NSTORE3][NUMFAILPFLAGS],FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR]);
14 static int general_average(int useonlynonfailed, int numbndtotry, int maxnumbndtotry, int startpl, int endpl, int i, int j, int k, int doingmhd, PFTYPE mhdlpflag, PFTYPE radlpflag, PFTYPE (*lpflagfailorig)[NSTORE2][NSTORE3][NUMFAILPFLAGS],FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom);
15 static int fixup_nogood(int startpl, int endpl, int i, int j, int k, int doingmhd, PFTYPE mhdlpflag, PFTYPE radlpflag, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR],FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom);
16 static int fixuputoprim_accounting(int i, int j, int k, PFTYPE mhdlpflag, PFTYPE radlpflag, int limitgammamhd, int limitgammarad, PFTYPE (*lpflag)[NSTORE2][NSTORE3][NUMPFLAGS],FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR], struct of_geom *geom, FTYPE *pr0, FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep);
17 static int fixup_negdensities(int whichtofix, int *fixed, int startpl, int endpl, int i, int j, int k, PFTYPE mhdlpflag, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR], struct of_geom *geom, FTYPE *pr0, FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep);
18 
19 static int superdebug_utoprim(FTYPE *pr0, FTYPE *pr, struct of_geom *ptrgeom, int whocalled);
20 
21 
22 
23 // whether to add radiation YFL4,YFL5 to gas YFL2,YFL3
24 #define YFLADDRADTOGAS 0
25 
26 
27 
30 int pre_fixup(int stage,FTYPE (*pv)[NSTORE2][NSTORE3][NPR])
31 {
32 
33  // grab b^2 flags (above fixup may change u or rho, so must do this after)
34  get_bsqflags(stage,pv);
35 
36 
37  return(0);
38 }
39 
40 
41 
44 int post_fixup(int stageit,int finalstep, SFTYPE boundtime, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR],FTYPE (*ucons)[NSTORE2][NSTORE3][NPR])
45 {
46  int stage,stagei,stagef;
47  int boundstage;
48 
49 #if(UTOPRIMADJUST!=0)
50 
51  //
52  // utoprim fixup of primitive solution
53 
54 
55 
56  if(SIMULBCCALC<=0){ stagei=STAGEM1; stagef=STAGEM1; }
57  else if(SIMULBCCALC==1) { stagei=STAGE0; stagef=STAGE2;}
58  else if(SIMULBCCALC==2) { stagei=STAGE0; stagef=STAGE5;}
59 
60  if(SIMULBCCALC>=1) boundstage=STAGE0;
61  else boundstage=STAGEM1;
62 
63 
64  for(stage=stagei;stage<=stagef;stage++){
65 
66 
67 
68  // first bound failure flag
69  // OPTMARK: could optimize bound of pflag since often failures don't occur (just ask if any failures first), although probably negligible performance hit
70  if(stage<STAGE2){
71  bound_pflag(boundstage, finalstep, boundtime, GLOBALPOINT(pflag), USEMPI);
72  if(stage!=STAGEM1) boundstage++;
73  }
74 
75 
76  // check for bad solutions and set as failure if good is reasonably bad
77 #if(CHECKSOLUTION)
78  fixup_checksolution(stage,pv,finalstep);
79 
80  // check solution changed pflag, so have to bound again
81  if(stage<STAGE2){
82  bound_pflag(boundstage, finalstep, boundtime, pflag, USEMPI);
83  if(stage!=STAGEM1) boundstage++;
84  }
85 
86 #endif
87 
88  // int long long nstepfake;
89  // nstepfake=nstep;
90  // nstep=0;
91  // image_dump(-4);
92  // nstep=nstepfake;
93 
94  // fixup before new solution (has to be here since need previous stage's failure flag)
95  fixup_utoprim(stage,pv,pbackup,ucons,finalstep);
96 
97  // after fixup_utoprim(), the floors/ceilings won't be satisfied anymore, especially near sharp jumps in densities, so repeat.
98  fixup(stage, pv, ucons, finalstep);
99 
100 
101 #if(0)
102  // GODMARK: I don't see why need to bound pflag since already done with using pflag
103  if(stage<STAGE2){
104  if(stage!=STAGEM1){
105  bound_pflag(boundstage, finalstep, boundtime, pflag, USEMPI);
106  boundstage++;
107  }
108  }
109 #endif
110 
111  }
112 #endif
113 
115  //
116  // standard fixup of floor
117  // in this case stageit=-1, so does all stages
118  // fixup(stageit,pv,finalstep);
119 
120 
121 
122 
123  return(0);
124 }
125 
126 
128 int post_fixup_nofixup(int stageit, int finalstep, SFTYPE boundtime, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR],FTYPE (*ucons)[NSTORE2][NSTORE3][NPR])
129 {
130 
131  fixup_utoprim_nofixup(STAGEM1,pv,pbackup,ucons,finalstep);
132 
133  return(0);
134 }
135 
136 
137 
138 
139 
140 
144 int fixup(int stage,FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep)
145 {
146  int i, j, k;
147  struct of_geom geomdontuse;
148  struct of_geom *ptrgeom=&geomdontuse;
149 
150 
151 
152  COMPZLOOP{
153  // dualfprintf(fail_file,"i=%d j=%d k=%d\n",i,j,k); fflush(fail_file);
154  get_geometry(i,j,k,CENT,ptrgeom);
155  if(fixup1zone(0,MAC(pv,i,j,k),MAC(ucons,i,j,k), ptrgeom,finalstep)>=1)
156  FAILSTATEMENT("fixup.c:fixup()", "fixup1zone()", 1);
157  }
158  return(0);
159 }
160 
161 
162 
164 int diag_fixup_correctablecheck(int docorrectucons, struct of_geom *ptrgeom)
165 {
166  int is_within_correctable_region;
167  int docorrectuconslocal;
168 
170  //
171  // determine if within correctable region
172  //
174  if( DOENOFLUX != NOENOFLUX ) {
175  is_within_correctable_region=((ptrgeom->i)>=Uconsevolveloop[FIS])&&((ptrgeom->i)<=Uconsevolveloop[FIE])&&((ptrgeom->j)>=Uconsevolveloop[FJS])&&((ptrgeom->j)<=Uconsevolveloop[FJE])&&((ptrgeom->k)>=Uconsevolveloop[FKS])&&((ptrgeom->k)<=Uconsevolveloop[FKE]);
176  }
177  else{
178  is_within_correctable_region=1; // assume diag_fixup() only called where ok to do change to ucons!
179  }
180 
181 
183  //
184  // determine if should do correction to ucons
185  // only correct once -- should really put correction somewhere else.
186  //
188  docorrectuconslocal=docorrectucons && is_within_correctable_region;
189 
190 
191  return(docorrectuconslocal);
192 
193 
194 }
195 
196 
197 
199 int count_whocalled(int i, int j, int k, int finalstep, int whocalled, CTYPE toadd)
200 {
201  int tscale;
202 
204  //
205  // Count times in diag_fixup() and who called diag_fixup()
206  // count every time corrects, not just on conserved quantity tracking time
207  //
209  if(DODEBUG){
210 
211  if(whocalled>=NUMFAILFLOORFLAGS || whocalled<COUNTNOTHING || i<-N1BND || i>N1-1+N1BND ||j<-N2BND || j>N2-1+N2BND ||k<-N3BND || k>N3-1+N3BND ){
212  dualfprintf(fail_file,"In diag_fixup() whocalled=%d for i=%d j=%d k=%d\n",whocalled,i,j,k);
213  myexit(24683463);
214  }
215 
216  if(whocalled>=COUNTREALSTART){
217  int indexfinalstep;
218  indexfinalstep=0;
219  TSCALELOOP(tscale) GLOBALMACP0A3(failfloorcount,i,j,k,indexfinalstep,tscale,whocalled)+=toadd;
220  if(finalstep){
221  indexfinalstep=1;
222  // iterate finalstep version
223  TSCALELOOP(tscale) GLOBALMACP0A3(failfloorcount,i,j,k,indexfinalstep,tscale,whocalled)+=toadd;
224  }
225  }// end if counting something
226 
227  }// end if DODEBUG
228 
229 
230  return(0);
231 
232 }
233 
234 
235 
239 int diag_fixup_dUandaccount(FTYPE *Ui, FTYPE *Uf, FTYPE *ucons, struct of_geom *ptrgeom, int finalstep, int whocalled, int docorrectuconslocal)
240 {
241  FTYPE dUincell[NPR];
242  int is_within_diagnostic_region;
243  FTYPE deltaUavg[NPR],Uiavg[NPR];
244  FTYPE Uprefixup[NPR],Upostfixup[NPR];
245  int pliter,pl;
246  int enerregion;
247 
248 
249 
251  //
252  // Get deltaUavg[] and also modify ucons if required and should
253  //
255 
256  if(DOENOFLUX != NOENOFLUX) { //SASMARKx: adjust the conserved quantity to correspond to the adjusted primitive quanitities
257  // Correction to conserved quantities not exactly accurate because using point values where should use averaged values
258  // notice that geometry comes after subtractions/additions of EOMs
259  UtoU(UDIAG,UEVOLVE,ptrgeom,Ui,Uprefixup); // convert from UDIAG -> UEVOLVE
260  UtoU(UDIAG,UEVOLVE,ptrgeom,Uf,Upostfixup); // convert from UDIAG -> UEVOLVE
261 
262  PALLLOOP(pl) deltaUavg[pl] = Uf[pl]-Ui[pl];
263 
264  if(docorrectuconslocal){
265  // correct ucons if requested
266  //adjust the averaged conserved quantity by the same amt. as the point conserved quantity
267  PALLLOOP(pl) ucons[pl] += Upostfixup[pl] - Uprefixup[pl];
268 
269  // old code: UtoU(UDIAG,UEVOLVE,ptrgeom,Uf,ucons); // convert from UNOTHING->returntype (jon's comment)
270  // the above line actually converts fixed up U from diagnostic form of U (with gdet)
271  // to evolution form of U (maybe withnogdet) and replaces the avg. conserved quantity (ADT)
272  }
273 
274  }
275  else if(0){
276 
277  // this method doesn't work:
278  UtoU(UEVOLVE,UDIAG,ptrgeom,ucons,Uiavg); // convert from UNOTHING->returntype
279 
280  if(docorrectuconslocal){
281  // notice that geometry comes after subtractions/additions of EOMs
282  UtoU(UDIAG,UEVOLVE,ptrgeom,Uf,ucons); // convert from UNOTHING->returntype
283  }
284 
285  PALLLOOP(pl) deltaUavg[pl] = Uf[pl]-Uiavg[pl];
286  }
287  else{
288  // original HARM method
289  // don't modify ucons. That is, we ignore docorrectuconslocal.
290 
291  PALLLOOP(pl) deltaUavg[pl] = Uf[pl]-Ui[pl];
292  }
293 
294 
295 
296  //only do aggregate accounting, after the fact (just before taking the new time step)
297  if(DOONESTEPDUACCOUNTING && whocalled==COUNTONESTEP || DOONESTEPDUACCOUNTING==0){
298 
300  //
301  // get correction
302  //
304  PALLLOOP(pl){
305 
306  // dUincell means already (e.g.) (dU0)*(\detg')*(dV') = integral of energy in cell = dUint0 in SM
307  // So compare this to (e.g.) (U0)*(\detg')*(dV') = U0*gdet*dV in SM
308  dUincell[pl]=dVF * deltaUavg[pl];
309 
310  if(DOFLOORDIAG){
311  // only store this diagnostic once (not for each enerregion)
312  // Note that unlike failfloorcount[], failfloordu[] is independent of fladd and fladdterms that are integrated simultaneously rather than in dump_ener.c
313  // Also note that failfloordu not stored in restart file, so like spatial debug info it is lost upon restart.
314  GLOBALMACP0A1(failfloordu,ptrgeom->i,ptrgeom->j,ptrgeom->k,pl)+=dUincell[pl];
315  }
316 
317  }// end over pl's
318 
319 
320 
321 
323  //
324  // Loop over ENERREGIONs
325  //
327  ENERREGIONLOOP(enerregion){
328 
329  // setup pointers to enerregion diagnostics
330  enerpos=enerposreg[enerregion];
331  fladd=fladdreg[enerregion];
332  fladdterms=fladdtermsreg[enerregion];
333 
334 
336  //
337  // determine if within diagnostic region
338  //
340  is_within_diagnostic_region=WITHINENERREGION(enerpos,ptrgeom->i,ptrgeom->j,ptrgeom->k);
341 
342 
344  //
345  // diagnostics (both for enerregion and single-region types)
346  //
348  if(is_within_diagnostic_region){
349 
350  PALLLOOP(pl){
351 
352  // dUincell means already (e.g.) (dU0)*(\detg')*(dV') = integral of energy in cell = dUint0 in SM
353  // So compare this to (e.g.) (U0)*(\detg')*(dV') = U0*gdet*dV in SM
354  dUincell[pl]=dVF * deltaUavg[pl];
355 
356  fladd[pl] += dUincell[pl];
357 
358  }// end over pl's
359  }// end if within diagnostic region
360 
361  }// end over enerregions
362 
363  }// end if doing accounting
364 
365  if(whocalled>=0 && whocalled!=COUNTONESTEP){
366 
368  //
369  // Loop over ENERREGIONs
370  //
372  ENERREGIONLOOP(enerregion){
373 
374  // setup pointers to enerregion diagnostics
375  enerpos=enerposreg[enerregion];
376  fladdterms=fladdtermsreg[enerregion];
377 
378 
380  //
381  // determine if within diagnostic region
382  //
384  is_within_diagnostic_region=WITHINENERREGION(enerpos,ptrgeom->i,ptrgeom->j,ptrgeom->k);
385 
386 
388  //
389  // diagnostics (both for enerregion and single-region types)
390  //
392  if(is_within_diagnostic_region){
393 
394  PALLLOOP(pl){
395 
396  // dUincell means already (e.g.) (dU0)*(\detg')*(dV') = integral of energy in cell = dUint0 in SM
397  // So compare this to (e.g.) (U0)*(\detg')*(dV') = U0*gdet*dV in SM
398  dUincell[pl]=dVF * deltaUavg[pl];
399 
400  fladdterms[whocalled][pl] += (SFTYPE)dUincell[pl];
401 
402 
403  }// end over pl's
404  }// end if within diagnostic region
405 
406  }// end over enerregions
407 
408  }// end if doing accounting
409 
410 
411  return(0);
412 }
413 
414 
415 
416 int consfixup_allzones(int finaluu, FTYPE (*pf)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR])
417 {
418 
419 
420  int i, j, k, pliter,pl;
421  struct of_geom *ptrgeom;
422  struct of_geom geomdontuse;
423 
424 
425  ptrgeom=&(geomdontuse);
426 
427  COMPZLOOP{
428  get_geometry(i, j, k, CENT, ptrgeom);
429  // account for change of conserved quantities
430  // Primitives have been modified by fixup1zone() in advance.c (floors).
431  // During this call, called from post_advance(), pf also modified by bounds (poledeath,gammadeath) and also post_fixup() (failures, checks, limits).
432  //
433  // ucons=unewglobal that stores last steps final substep version of ucum that is full U[]
434  // ucons has yet to be modified at all, so is true conserved quantity without corrections (as long as avoided corrections to ucons during other diag_fixup calls).
435  // GODMARK: So this method only works if NOENOFLUX==1, since otherwise *need* to modify U[] during modification of p[] since know how much to modify.
436 
437  consfixup_1zone(finaluu, i,j,k, ptrgeom, &MACP0A1(pf,i,j,k,0), &MACP0A1(ucons,i,j,k,0));
438 
439 
440  }
441 
442 
443  return(0);
444 
445 }
446 
447 
448 int consfixup_1zone(int finaluu, int i, int j, int k, struct of_geom *ptrgeom, FTYPE *pf, FTYPE *ucons)
449 {
450  if(ENSURECONS==0 || (EOMRADTYPE==EOMRADNONE)) return(0);
451 
452  int pliter,pl;
453  // now that have averaged values, try to enforce energy conservation by borrowing from radiation
454  FTYPE *pp=pf;
455  struct of_state qp;
456  get_state(pp,ptrgeom,&qp);
457  int uutype=UNOTHING;
458  FTYPE uu[NPR],uuabs[NPR];
459  primtoU(uutype,pp,&qp,ptrgeom,uu,uuabs);
460  FTYPE uu0[NPR];
461  if(finaluu==1){
462 #if(WHICHEOM==WITHGDET)
463  PLOOP(pliter,pl) uu0[pl]=ucons[pl]*ptrgeom->igdetnosing; // put in UNOTHING form
464 #else
465  PLOOP(pliter,pl) uu0[pl]=ucons[pl]*ptrgeom->ieomfuncnosing[pl]; // put in UNOTHING form
466 #endif
467  }
468  else{
469  // PLOOP(pliter,pl) uu0[pl] = GLOBALMACP0A1(uu0old,i,j,k,pl); // USE OF GLOBALS from phys.tools.rad.c // already in UNOTHING form
470  }
471 
472 
473 
474  FTYPE uunew1[NPR];
475  PLOOP(pliter,pl) uunew1[pl]=uu[pl];
476  //
477  FTYPE dugas[4];
478  int jj;
479  DLOOPA(jj) uunew1[UU+jj] = uu[UU+jj];
480  DLOOPA(jj) dugas[jj] = uu[UU+jj]-uu0[UU+jj];
481  DLOOPA(jj) uunew1[URAD0+jj] = uu0[URAD0+jj] - dugas[jj];
482 
483 
484 
485 #if(0)
486  FTYPE uunew2[NPR];
487  PLOOP(pliter,pl) uunew2[pl]=uu[pl];
488  //
489  FTYPE durad[4];
490  DLOOPA(jj) uunew2[URAD0+jj] = uu[URAD0+jj];
491  DLOOPA(jj) durad[jj] = uu[URAD0+jj]-uu0[URAD0+jj];
492  DLOOPA(jj) uunew2[UU+jj] = uu0[UU+jj] - durad[jj];
493  //
494  // choose which or how much of each uunew and uunew2
495  FTYPE uunewfinal[NPR];
496  PLOOP(pliter,pl) uunewfinal[pl] = uu[pl];
497  //
498  DLOOPA(jj){
499  uunewfinal[UU+jj] = 0.5*(uunew1[UU+jj] + uunew2[UU+jj]);
500  uunewfinal[URAD0+jj] = 0.5*(uunew1[URAD0+jj] + uunew2[URAD0+jj]);
501  }
502 #endif
503 
504  // now invert just radiation
505  int showmessages=0;
506  int allowlocalfailurefixandnoreport=1;
507  int whichcap=CAPTYPEBASIC; // finalcheck type
508 
509  int didrad=0;
510  if(-uunew1[URAD0]<-uu[URAD0]){ // only modify radiation if forcing less radiation, not more as that can run-away
512  PFTYPE lpflag=0;
513  PFTYPE lpflagrad=0;
514  FTYPE pprad[NPR];
515  PLOOP(pliter,pl) pprad[pl]=pp[pl];
516  // u2p_rad takes UNOTHING form
517  u2p_rad(showmessages, allowlocalfailurefixandnoreport,GAMMAMAXRADIMPLICITSOLVER,whichcap,uunew1,pprad,ptrgeom,&lpflag,&lpflagrad);
518  int radinvmod=(int)(lpflagrad);
519  if(RADINVOK(radinvmod) && isfinite(pprad[URAD0])==1 && isfinite(pprad[URAD1])==1 && isfinite(pprad[URAD2])==1 && isfinite(pprad[URAD3])==1 && pprad[URAD0] < pp[URAD0]){
520  PLOOP(pliter,pl) if(RADFULLPL(pl)) pp[pl] = pprad[pl];
521  didrad=1;
522  }
523  else{
524  didrad=0;
525  // dualfprintf(fail_file,"issue ijk=%d %d %d radinvmod=%d\n",i,j,k,radinvmod);
526  // PLOOP(pliter,pl) if(RADFULLPL(pl)) dualfprintf(fail_file,"pprad[%d]=%g\n",pl,pprad[pl]);
527  }
528  }
529 
530 
531 #if(0)
532  if(0&&didrad==0){
533  int finalstep=finaluu;
534  int eomtypelocal=EOMTYPE;
535  int whichmethod=MODEPICKBEST; // try to choose best option for this "external" inversion
536  int modprim=0;
537  int checkoninversiongas=CHECKONINVERSION;
538  int checkoninversionrad=CHECKONINVERSIONRAD;
539  FTYPE dissmeasure=0.0;
540 
541 
542  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
543  // initialize counters
544  newtonstats.nstroke=newtonstats.lntries=0;
545  // KORALNOTE: If make newtonstats.tryconv~convabs, then if convabs~1E-12, then MHD inversion may return error~1E-10 in terms of how measured with f_error_check(), so must try harder than expected.
546  newtonstats.tryconv=1E-3;
547  newtonstats.tryconvultrarel=1E-5;
548  newtonstats.extra_newt_iter=1;
549  newtonstats.extra_newt_iter_ultrarel=1;
550 #define MINTRYCONVFORMHDINVERSION (1E-4) // assume not failure if got down to this much. -- don't have to be related to implicit allowance.
551 
552  newtonstats.mintryconv=MINTRYCONVFORMHDINVERSION;
553  newtonstats.maxiter=100;
554 
555  FTYPE pptry[NPR];
556  PLOOP(pliter,pl) pptry[pl] = pf[pl];
557  MYFUN(Utoprimgen(showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep,&eomtypelocal,whichcap,whichmethod,modprim,EVOLVEUTOPRIM,UNOTHING,uunewfinal, &qp, ptrgeom, dissmeasure, pptry, pptry, &newtonstats),"step_ch.c:advance()", "Utoprimgen", 1);
558 
559  PFTYPE *lpflag,*lpflagrad;
560  lpflag=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
561  lpflagrad=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
562 
563 
564  if(IFUTOPRIMFAILSOFT(*lpflag)){
565  // PLOOP(pliter,pl) pf[pl] = pptry[pl];
566  }
567  else if(IFUTOPRIMRADFAIL(*lpflagrad)){
568  }
569  else if( IFUTOPRIMFAIL(*lpflag) || IFUTOPRIMRADFAIL(*lpflagrad) ){
570  }
571  else{
572  PLOOP(pliter,pl) pf[pl] = pptry[pl];
573  }
574  }
575 #endif
576 
577  struct of_state qf;
578  get_state(pf,ptrgeom,&qf);
579  FTYPE uf[NPR],ufabs[NPR];
580  primtoU(uutype,pf,&qf,ptrgeom,uf,ufabs); // should be closer to having uf[UU]+uf[URAD0] = ucons[UU]+ucons[URAD0]
581 
582  FTYPE uudiag[NPR],ufdiag[NPR];
583  UtoU(UNOTHING,UDIAG,ptrgeom,uu,uudiag); // convert from UNOTHING -> UDIAG
584  UtoU(UNOTHING,UDIAG,ptrgeom,uf,ufdiag); // convert from UNOTHING -> UDIAG
585 
586 
587  // Get deltaUavg[] and also modify ucons if required and should
588  int whocalled=COUNTUCONSFIXUP;
589  int docorrectuconslocal=0;
590  int finalstep=finaluu;
591  diag_fixup_dUandaccount(uudiag, ufdiag, ucons, ptrgeom, finalstep, whocalled, docorrectuconslocal);
592 
593 
594 
595 
596  // so exact energy conservation at cost of unknown effect on radiation
597  // so one-step accounting below will include a floor for both gas and radiation, but sum of floors will always be zero net gain of energy-momentum as long as radiation has radinvmod==0
598 
599  return(0);
600 }
601 
602 
603 
609 int diag_fixup_allzones(FTYPE (*pf)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR])
610 {
611 
612  int i, j, k, pliter,pl;
613  struct of_geom *ptrgeom;
614  struct of_geom geomdontuse;
615 
616  if(DOENOFLUX!=NOENOFLUX){
617  dualfprintf(fail_file,"Cannot use diag_fixup_allzones() with DOENOFLUX!=NOENOFLUX\n");
618  myexit(3487622211);
619  }
620 
621  ptrgeom=&(geomdontuse);
622 
623  COMPZLOOP{
624  get_geometry(i, j, k, CENT, ptrgeom);
625  // account for change of conserved quantities
626  // Primitives have been modified by fixup1zone() in advance.c (floors).
627  // During this call, called from post_advance(), pf also modified by bounds (poledeath,gammadeath) and also post_fixup() (failures, checks, limits).
628  //
629  // ucons=unewglobal that stores last steps final substep version of ucum that is full U[]
630  // ucons has yet to be modified at all, so is true conserved quantity without corrections (as long as avoided corrections to ucons during other diag_fixup calls).
631  // GODMARK: So this method only works if NOENOFLUX==1, since otherwise *need* to modify U[] during modification of p[] since know how much to modify.
632 
633  int docorrectucons=(DOENOFLUX != NOENOFLUX); // make any needed corrections if doing corrections
634  int finalstep=1; // if here, always on finalstep=1
635  FTYPE Uf[NPR]; // for returning back pf->Uf result so don't have to repeat if needed later
636  diag_fixup_Ui_pf(docorrectucons,MAC(ucons,i,j,k),MAC(pf,i,j,k),ptrgeom,finalstep,COUNTONESTEP, Uf); // Uf in UDIAG form
637 
638  FTYPE *pr=MAC(pf,i,j,k);
639 
640  int map[NPR];
641  FTYPE uconmap[NPR];
642  PLOOP(pliter,pl){
643  uconmap[pl]=1.0; // default
644 
645  if(pl==RHO) map[pl]=YFL1;
646  else if(pl==UU) map[pl]=YFL2;
647  else if(pl==U3) map[pl]=YFL3;
648  else if(pl==URAD0) map[pl]=YFL4;
649  else if(pl==URAD3) map[pl]=YFL5;
650  else map[pl]=VARNOTDEFINED;
651  }
652 
653 
654  FTYPE ucon[NDIM],others[NUMOTHERSTATERESULTS];
655  ucon_calc(pr,ptrgeom,ucon,others);
656  if(YFL1>=0) uconmap[YFL1]=ucon[TT];
657  if(YFL2>=0) uconmap[YFL2]=-ucon[TT]; // NOTEMARK: Same sign as in other places like utoprimgen.c
658  if(YFL3>=0) uconmap[YFL3]=ucon[TT];
659 
660  if(YFL4>=0 || YFL5>=0){
661  FTYPE uradcon[NDIM],othersrad[NUMOTHERSTATERESULTS];
662  ucon_calc(&pr[URAD1-U1],ptrgeom,uradcon,othersrad);
663  if(YFL4>=0) uconmap[YFL4]=-uradcon[TT]; // NOTEMARK: Same sign as in other places like utoprimgen.c
664  if(YFL5>=0) uconmap[YFL5]=uradcon[TT];
665  }
666 
667  // assume fixed floor for YFLx like at t=0
668  FTYPE offset[NPR];
669 
670  FTYPE rhofloor=pr[RHO]*NUMEPSILON*10.0;
671  FTYPE vfloor=NUMEPSILON*10.0;
672  FTYPE enfloor=ERADLIMIT;
673  if(URAD0>=0) enfloor+= (pr[URAD0])*NUMEPSILON*10.0;
674  PLOOP(pliter,pl) offset[pl]=SMALL;
675  if(YFL1>=0) offset[YFL1] = SMALL + rhofloor; // rho floor
676  if(YFL2>=0) offset[YFL2] = SMALL + rhofloor*vfloor*vfloor + UULIMIT; // -T^t_t-rho u^r floor
677  if(YFL3>=0) offset[YFL3] = SMALL + rhofloor*vfloor; // T^t_phi floor
678  if(YFL4>=0) offset[YFL4] = SMALL + enfloor; // -R^t_t floor
679  if(YFL5>=0) offset[YFL5] = SMALL + enfloor*vfloor; // R^t_\phi floor
680 
681 
682  FTYPE uconsnothing[NPR];
683  UtoU(UEVOLVE,UNOTHING,ptrgeom,MAC(ucons,i,j,k),uconsnothing);
684 
685  FTYPE Ufnothing[NPR];
686  UtoU(UDIAG,UNOTHING,ptrgeom,Uf,Ufnothing);
687 
688  int mapvar;
689  PLOOP(pliter,pl){
690  mapvar=map[pl];
691  if(mapvar>=0){
692 
693  // effective source term for floor scalar accounting for all changes to pl not accounted for by conserved quantity additions (that includes no floors or failures or anything else except fluxes)
694  // Assumes floor and mass have same velocity
695  // dpl can actually be negative or positive, but only negative when failure
696  // FTYPE pl=MACP0A1(pf,i,j,k,PL); // new final total
697  FTYPE pltotal=Ufnothing[pl]/uconmap[mapvar];
698  //FTYPE dpl=pl - uconsnothing[pl]/uconmap[mapvar];
699  FTYPE dpl=(Ufnothing[pl] - uconsnothing[pl])/uconmap[mapvar];
700 
701  if(YFLADDRADTOGAS){
702  int plalt;
703  if(pl==URAD0){
704  plalt=UU;
705  dpl+=(Ufnothing[plalt] - uconsnothing[plalt])/uconmap[map[plalt]];
706  }
707  if(pl==URAD3){
708  plalt=U3;
709  dpl+=(Ufnothing[plalt] - uconsnothing[plalt])/uconmap[map[plalt]];
710  }
711  }
712 
713  FTYPE plfl;
714  // FTYPE plfl = MACP0A1(pf,i,j,k,mapvar)*pltotal); // final plfl without source term (if failure, then yflx and pl come from averaging, then plfl and pltotal will not be related by conserved fluxes and (e.g.) yflx can become >1
715  // FTYPE yflx = uconsnothing[mapvar]/uconsnothing[pl]; // yflx expected from ucons that accounts for fluxes but no sources, but uconsnothing[pl] could be negative or zero and would have led to failure
716  plfl = uconsnothing[mapvar]/uconmap[mapvar]; // plfl from ucons, not consistent with final yflx,pltotal if failure, but averaged yflx probably worse than yflx linked to pltotal
717  // if(plfl<SMALL) plfl=SMALL;
718 
719  FTYPE plflfinal = plfl + dpl;
720  if(1&&(mapvar==YFL2 || mapvar==YFL4)){ // just energy densities. Can't apply to angular momenta that can be any sign. Could apply to density, but doesn't seem to need it.
721  // at least for non-densities, especially energy densities, having near 0 or negative values leads to an instability and crazy run-away in the values due to fluxes.
722  // So won't be able to track losses of energy, only gains, unless split gains and losses.
723  // Or maybe need floor at t=0 at least so that not dealing with crazy small values?
724  FTYPE offsetfull=0.0;
725  if(pl==UU&&0){ // need to compare to zero when rest-mass added
726  offsetfull=offset[mapvar]-uconsnothing[RHO]/ucon[TT];
727  }
728  else offsetfull=offset[mapvar];
729  if(plflfinal<offsetfull) plflfinal=offsetfull; // allow flux and source to compensate to give final >0 quantity
730  }
731 
732 #if(0)
733  // plfl could have been negative, as if failure or other process pulled away total rest-mass. Since force not have floor on value, then that means plfl can go greater than pltotal sometimes. So avoid.
734  if(plflfinal>pltotal) plflfinal=pltotal; // limit so effective true Y_fl<=1
735 #endif
736 
737  // set actual total change in effective floor
738  if(DOYFL==1){ // here get true Y_fl=plflfinal/pltotal
739  MACP0A1(pf,i,j,k,mapvar) = plflfinal/(SMALL+fabs(pltotal)); // newYflx = newplfl / newpltotal
740  }
741  else if(DOYFL==2){ // source term to density scalar, assuming pf was evolved via fluxes already for YFLx itself, so here we just add error term from normal evolved quantities
742  // if(mapvar==YFL4 && plflfinal<ERADLIMIT) plflfinal=ERADLIMIT;
743  MACP0A1(pf,i,j,k,mapvar) = plflfinal;
744  }
745  // dualfprintf(fail_file,"pltotal=%g dpl=%g plfl=%g plflfinal=%g yfl=%g\n",pltotal,dpl,plfl,plflfinal,MACP0A1(pf,i,j,k,YFL));
746 
747 
748  } // end if doing this Yflx
749  }// end loop over Yflx
750  }// end spatial loop
751 
752 
753  return(0);
754 
755 }
756 
757 
758 
764 int diag_fixup(int docorrectucons, FTYPE *pr0, FTYPE *pr, FTYPE *uconsinput, struct of_geom *ptrgeom, int finalstep, int doingmhdfixup, int whocalled)
765 {
766  struct of_state q;
767  FTYPE Uicent[NPR],Ufcent[NPR];
768  int failreturn;
769  void UtoU(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
770  FTYPE deltaUavg[NPR],Uiavg[NPR];
771  FTYPE Uprefixup[NPR],Upostfixup[NPR];
772  int docorrectuconslocal;
773  int pliter,pl;
774 
775  // store ucons and only change if needed (and handle avoidance of B1,B2,B3 in case ucons points to unewglobal staggered field, while here we operate on centers)
776  FTYPE ucons[NPR];
777  if(uconsinput!=NULL){
778  PLOOP(pliter,pl) ucons[pl]=uconsinput[pl];
779  }
780 
781 #if(DOSUPERDEBUG)
782  superdebug_utoprim(pr0,pr,ptrgeom,whocalled);
783  // collect values for non-failed and failed zones
784 #endif
785 
786 
787 
788  // count whocalled diag_fixup()
789  if(doingmhdfixup) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, finalstep, whocalled,1);
790 
791 
792 
794  //
795  // Account for changes in primitives or conserved quantities due to fixups (floor or failures or any other thing that can call diag_fixup()
796  //
797  // only account if on full timestep
798  // ucum (unew) only inverted to primitives on final substep. Any other conserved or primitive corrections do not matter since they only affected fluxes that go into true conserved quantity that is ucum (unew)
799  //
801 
802  if(finalstep > 0){
803 
805  // determine if within correctable region
807  docorrectuconslocal=diag_fixup_correctablecheck(docorrectucons,ptrgeom);
808 
809 
810 
812  //
813  // Get Uicent and Ufcent. Don't do this inside enerregion because no point since assume diag_fixup() called in limited regions of i,j,k anyways.
814  //
815  // only account if within active zones for that region
816  //
817  // Only valid if not higher order method or if MERGED method where conserved (except field) are at points as also the primitives are
818  //
820 
821 
822  // before any changes
823  failreturn=get_state(pr0,ptrgeom,&q);
824  if(failreturn>=1) dualfprintf(fail_file,"get_state(1) failed in fixup.c, why???\n");
825  failreturn=primtoU(UDIAG,pr0,&q,ptrgeom,Uicent, NULL);
826  if(failreturn>=1) dualfprintf(fail_file,"primtoU(1) failed in fixup.c, why???\n");
827 
828 
829  // after any changes
830  failreturn=get_state(pr,ptrgeom,&q);
831  if(failreturn>=1) dualfprintf(fail_file,"get_state(2) failed in fixup.c, why???\n");
832  failreturn=primtoU(UDIAG,pr,&q,ptrgeom,Ufcent, NULL);
833  if(failreturn>=1) dualfprintf(fail_file,"primtoU(2) failed in fixup.c, why???\n");
834 
835  // if Uicent and Ufcent are both from pi and pf at CENT, then B1,B2,B3 entries are agreeably located even for FLUXB==FLUXCTSTAG
836 
837  // Get deltaUavg[] and also modify ucons if required and should
838  diag_fixup_dUandaccount(Uicent, Ufcent, ucons, ptrgeom, finalstep, whocalled, docorrectuconslocal);
839 
840 
841  if(uconsinput!=NULL && docorrectuconslocal){
842 
843  // copy over ucons result in case changed.
844  PLOOP(pliter,pl){
845  // if staggered field, avoid modifying field since at FACEs, not CENT where pr lives.
846  if(BPL(pl)==0 && FLUXB==FLUXCTSTAG || FLUXB==FLUXCTTOTH){
847  uconsinput[pl] = ucons[pl];
848  }
849  }
850  }
851 
852 
853  }// end if finalstep>0
854 
855 
856 
857  return(0);
858 }
859 
860 
861 
867 int diag_fixup_Ui_pf(int docorrectucons, FTYPE *Uievolve, FTYPE *pf, struct of_geom *ptrgeom, int finalstep, int whocalled, FTYPE *Uf)
868 {
869  struct of_state q;
870  FTYPE Ufcent[NPR],Uicent[NPR],uconsinput[NPR],ucons[NPR];
871  int failreturn;
872  int pliter,pl,enerregion;
873  void UtoU(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
874  int docorrectuconslocal;
875 
876 
877 
878 
879 
880  // count whocalled diag_fixup()
881  count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, finalstep, whocalled,1);
882 
883 
884  if(finalstep > 0){
885 
886  // determine if within correctable region
887  docorrectuconslocal=diag_fixup_correctablecheck(docorrectucons,ptrgeom);
888 
889 
890 
892  //
893  // Get ucons
894  //
896 
897  // GODMARK: NOENOFLUX==0 not accounted for (have to change unewglobal or something like that)
898  PLOOP(pliter,pl) ucons[pl]=Uievolve[pl];
899 
900 
902  //
903  // Get Ufcent(pf[cent])
904  //
906 
907  failreturn=get_state(pf,ptrgeom,&q);
908  if(failreturn>=1) dualfprintf(fail_file,"get_state(2) failed in fixup.c, why???\n");
909  failreturn=primtoU(UDIAG,pf,&q,ptrgeom,Ufcent, NULL);
910  if(failreturn>=1) dualfprintf(fail_file,"primtoU(2) failed in fixup.c, why???\n");
911 
912  if(Uf!=NULL) PLOOP(pliter,pl) Uf[pl]=Ufcent[pl];// store result for returning before gets modified
913 
915  //
916  // Get Uicent
917  //
919 
920  // UEVOLVE -> UDIAG
921  // Assumes that Uievolve is like unewglobal and is at general U[] position (i.e. U[B1..B3] staggered and otherwise centered for FLUXB==FLUXCTSTAG)
922  UtoU(UEVOLVE,UDIAG,ptrgeom,Uievolve,Uicent);
923 
924  // Override B1..B3 with correct centered versions (correct both for value and geometry)
925  // ensure B^i is really at center even if FLUXB==FLUXCTSTAG (that would have Ui[B1..B3] at staggered)
926  // Assumes, as very generally true, that U[B1..B3] never change and can never be adjusted.
927  PLOOPBONLY(pl) Uicent[pl]=Ufcent[pl];
928 
929  PFTYPE *lpflag,*lpflagrad;
930  lpflag=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
931  lpflagrad=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
932 
933  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
934  // dualfprintf(fail_file,"lpflag=%d lpflagrad=%d\n",*lpflag,*lpflagrad);
935  // }
936 
937  if(*lpflag>UTOPRIMNOFAIL){
938  // then assume fixup_utoprim() needs to operate and will also handle accounting
939  PLOOP(pliter,pl) if(RADPL(pl)==0) Ufcent[pl] = Uicent[pl];
940  }
941  if(IFUTOPRIMRADFAIL(*lpflagrad)){
942  // then assume fixup_utoprim() needs to operate and will also handle accounting
943  PLOOP(pliter,pl) if(RADPL(pl)==1) Ufcent[pl] = Uicent[pl];
944  }
945 
946 
947 
949  //
950  // Get deltaUavg[] and also modify ucons if required and should
951  //
953  diag_fixup_dUandaccount(Uicent, Ufcent, ucons, ptrgeom, finalstep, whocalled, docorrectuconslocal);
954 
955 
956  if(docorrectuconslocal){
957  // copy over ucons result in case changed.
958  PLOOP(pliter,pl){
959  // if staggered field, avoid modifying field since at FACEs, not CENT where pr lives.
960  if(BPL(pl)==0 && FLUXB==FLUXCTSTAG || FLUXB==FLUXCTTOTH){
961  uconsinput[pl] = ucons[pl];
962  }
963  }
964  }
965 
966 
967  }// end if finalstep>0
968 
969 
970 
971  return(0);
972 }
973 
974 
975 
976 
982 int diag_fixup_U(int docorrectucons, FTYPE *Ui, FTYPE *Uf, FTYPE *uconsinput, struct of_geom *ptrgeom, int finalstep,int whocalled)
983 {
984  FTYPE Uicent[NPR],Ufcent[NPR];
985  struct of_state q;
986  int failreturn;
987  int pliter,pl,enerregion, tscale;
988  void UtoU(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
989  int docorrectuconslocal;
990 
991 
992  // store ucons and only change if needed (and handle avoidance of B1,B2,B3 in case ucons points to unewglobal staggered field, while here we operate on centers)
993  FTYPE ucons[NPR];
994  if(uconsinput!=NULL){
995  PLOOP(pliter,pl) ucons[pl]=uconsinput[pl];
996  }
997 
998  // count whocalled diag_fixup()
999  count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, finalstep, whocalled,1);
1000 
1001 
1002 
1003  if(finalstep>0){ // only account if on full timestep (assume only called if finalstep==1
1004 
1005 
1007  // determine if within correctable region
1009  docorrectuconslocal=diag_fixup_correctablecheck(docorrectucons,ptrgeom);
1010 
1011 
1013  //
1014  // First get correction (don't do inside enerregion loop since would be overly expensive and assume will need correction for at least one enerregion)
1015  //
1017 
1019  //
1020  // Change ucons (GODMARK: assumes Uf at CENT since uses single ptrgeom -- even though ucons is normally capable of being staggered for B1..B3)
1021  //
1023  if(DOENOFLUX != NOENOFLUX){ // JONMARK
1024  // notice that geometry comes after subtractions/additions of EOMs
1025  UtoU(UDIAG,UEVOLVE,ptrgeom,Uf,ucons); // convert from UDIAG->UEVOLVE
1026  }
1027 
1028 
1029  // get Uicent and Ufcent
1030  // Assumes that Ui is like unewglobal and is at general U[] position (i.e. U[B1..B3] staggered and otherwise centered for FLUXB==FLUXCTSTAG)
1031  PLOOP(pliter,pl){
1032  Uicent[pl]=Ui[pl];
1033  Ufcent[pl]=Uf[pl];
1034  }
1035 
1036  // ensure B^i is really at center even if FLUXB==FLUXCTSTAG (that would have Ui[B1..B3] at staggered)
1037  // Assumes, as very generally true, that U[B1..B3] never change and can never be adjusted.
1038  PLOOPBONLY(pl) Uicent[pl]=Ufcent[pl];
1039 
1040 
1041  // Get deltaUavg[] and also modify ucons if required and should
1042  diag_fixup_dUandaccount(Uicent, Ufcent, ucons, ptrgeom, finalstep, whocalled, docorrectuconslocal);
1043 
1044  if(uconsinput!=NULL && docorrectuconslocal){
1045  // copy over ucons result in case changed.
1046  PLOOP(pliter,pl){
1047  // if staggered field, avoid modifying field since at FACEs, not CENT where pr lives.
1048  if(BPL(pl)==0 && FLUXB==FLUXCTSTAG || FLUXB==FLUXCTTOTH){
1049  uconsinput[pl] = ucons[pl];
1050  }
1051  }
1052  }
1053 
1054 
1055  }
1056 
1057 
1058 
1059 
1060  return(0);
1061 }
1062 
1063 
1064 
1065 
1066 #if(VARTOINTERP==PRIMTOINTERP_GDETFULLVERSION_WALD)
1067 #define FIXUPTYPE 0 // or else would create spurious Poynting flux
1068 #else
1069 #define FIXUPTYPE 0 // too expensive if inversion fails alot as can happen near floors, near poles, or with radiation.
1070 #endif
1071 
1072 
1073 
1074 
1075 
1076 int fixup1zone(int docorrectucons, FTYPE *pr, FTYPE *uconsinput, struct of_geom *ptrgeom, int finalstep)
1077 {
1078  int pliter,pl;
1079  int ip, jp, im, jm;
1080  FTYPE bsq, del;
1081  FTYPE r, th, X[NDIM];
1082  FTYPE ftempA,ftempB;
1083  struct of_state q;
1084  struct of_state dq;
1085  FTYPE prfloor[NPR],prceiling[NPR];
1086  FTYPE prdiag[NPR];
1087  FTYPE pr0[NPR];
1088  FTYPE prmhdnew[NPR];
1089  FTYPE U[NPR],U0[NPR];
1090  int checkfl[NPR];
1091  int failreturn;
1092  int didchangeprim;
1093  FTYPE scalemin[NPR];
1094  // FTYPE ucovzamo[NDIM];
1095  // FTYPE uconzamo[NDIM];
1096  FTYPE dprmhd[NPR];
1097  FTYPE prmhd[NPR];
1098  FTYPE dU[NPR];
1099  // FTYPE P,Pnew;
1100  int jj;
1101  int badinversion;
1102  PFTYPE oldmhdpflag,oldradpflag;
1103 
1104 
1105 
1106  // store ucons and only change if needed (and handle avoidance of B1,B2,B3 in case ucons points to unewglobal staggered field, while here we operate on centers)
1107  FTYPE ucons[NPR];
1108  if(uconsinput!=NULL){
1109  PLOOP(pliter,pl) ucons[pl]=uconsinput[pl];
1110  }
1111 
1112 
1113  // assign general floor variables
1114  // whether to check floor condition
1115  PALLLOOP(pl){
1116  checkfl[pl]=0;
1117  pr0[pl]=pr[pl];
1118  prmhd[pl]=pr0[pl];
1119  prdiag[pl]=pr0[pl];
1120  }
1121 
1122  // shouldn't fail since before and after states should be ok, as
1123  // long as would have changed the value. Check will occur if
1124  // simulation continues ok. Could place check inside if below.
1125  didchangeprim=0;
1126 
1127 
1128 
1130  //
1131  // Set which quantities to check
1132  //
1134  if(DOEVOLVERHO){
1135  checkfl[RHO]=1;
1136  }
1137  if(DOEVOLVEUU){
1138  checkfl[UU]=1;
1139  }
1140  // KORALTODO: Keep as mhd only for now.
1141  int DOEVOLVEURAD0=PRAD0>=0 && EOMRADTYPE!=EOMRADNONE;
1142  if(DOEVOLVEURAD0) checkfl[PRAD0]=1;
1143 
1144 
1146  //
1147  // limit gamma wrt normal observer -- this can change b^2, so do this first.
1148  //
1150 #if(WHICHVEL==VELREL4)
1151  // int docorrectucons=(DOENOFLUX != NOENOFLUX);
1152  // didchangeprim=0;
1153 
1154  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
1155  // dualfprintf(fail_file,"BEFORE IN FIXUP1ZONE LIMITGAMMA: finalstep=%d\n",finalstep);
1156  // }
1157  failreturn=limit_gamma(docorrectucons,GAMMAMAX,GAMMAMAXRAD,prmhd,ucons,ptrgeom,-1);
1158  if(failreturn>=1) FAILSTATEMENT("fixup.c:fixup()", "limit_gamma()", 1);
1159  if(failreturn==-1) didchangeprim=1;
1160  // PALLLOOP(pl) prdiag[pl]=prmhd[pl];
1161  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
1162  // dualfprintf(fail_file,"AFTER IN FIXUP1ZONE LIMITGAMMA: didchangeprim=%d\n",didchangeprim);
1163  // }
1164 
1165  // if(didchangeprim&&FLOORDIAGS){// FLOORDIAGS includes fail diags
1166  // int doingmhdfixup=1;
1167  // diag_fixup(docorrectucons,prdiag, prmhd, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTLIMITGAMMAACT);
1168  // PALLLOOP(pl) prdiag[pl]=prmhd[pl];
1169  // }
1170 
1171 #endif// end if WHICHVEL==VEL4REL
1172 
1173 
1174 
1176  //
1177  // Only apply floor if cold or hot GRMHD
1178  //
1180  if(DOEVOLVERHO||DOEVOLVEUU||DOEVOLVEURAD0){
1181 
1182 
1184  //
1185  // get floor value (computes, e.g., bsq)
1186  //
1188  set_density_floors(ptrgeom,prmhd,prfloor,prceiling);
1189  scalemin[RHO]=RHOMINLIMIT;
1190  scalemin[UU]=UUMINLIMIT;
1191  if(URAD0>=0) scalemin[URAD0]=ERADLIMIT;
1192 
1193 
1194 
1196  //
1197  // Set super low floor
1198  //
1200  PALLLOOP(pl){
1201  if(checkfl[pl]){
1202  if(prfloor[pl]<scalemin[pl]) prfloor[pl]=scalemin[pl];
1203  }
1204  }
1205 
1206 
1208  //
1209  // Get new primitive if went beyond floor
1210  //
1212 
1214  PALLLOOP(pl){
1215  prmhdnew[pl]=prmhd[pl];
1216  }
1217 
1218  PALLLOOP(pl){
1219  if ( checkfl[pl]&&(prmhd[pl] < prfloor[pl] && prmhd[pl]<prceiling[pl]) ){
1220  didchangeprim=1;
1221  //dualfprintf(fail_file,"%d : %d %d %d : %d : %d : %21.15g - %21.15g\n",pl,ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,checkfl[pl],prfloor[pl],prmhd[pl]);
1222  // only add on full step since middle step is not really updating primitive variables
1223  prmhdnew[pl]=prfloor[pl];
1224  }
1225  }
1226 
1227  PALLLOOP(pl){
1228  if ( checkfl[pl]&&(prmhd[pl] > prfloor[pl] && prmhd[pl]>prceiling[pl]) ){
1229  didchangeprim=1;
1230  //dualfprintf(fail_file,"%d : %d %d %d : %d : %d : %21.15g - %21.15g\n",pl,ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,checkfl[pl],prfloor[pl],prmhd[pl]);
1231  // only add on full step since middle step is not really updating primitive variables
1232  prmhdnew[pl]=prceiling[pl];
1233  }
1234  }
1235 
1236 
1237 
1238 
1240  //
1241  // ONLY do something if want lower than floor
1242  //
1244  if(didchangeprim){
1245 
1246 #if(FIXUPTYPE==0)
1247  // effectively adds mass/internal energy in comoving frame, which can lead to instabilities as momentum is added
1248  // For example, occurs on poles where u^r\sim 0 (stagnation surface) which launches artificially high u^t stuff only because goes below floor for a range of radii and so adds momentum to low density material
1249  //
1250  PALLLOOP(pl){
1251  prmhd[pl]=prmhdnew[pl];
1252  }
1253 
1254 
1255 #elif(FIXUPTYPE==1 || FIXUPTYPE==2)
1256  // mass and internal energy added in frame not necessarily the comoving frame
1257  // using a frame not directly associated with comoving frame avoids arbitrary energy-momentum growth
1258  // GODMARK: FIXUPTYPE==1 doesn't exactly match between when b^2/\rho_0>BSQORHOULIMIT such that amount of mass added will force equality of b^2/\rho_0==BSQORHOLIMIT, so this may lead to problems.
1259  // physically FIXUPTYPE==1 models some non-local transport of baryons and energy to a location that supposedly occurs when b^2/rho_0 is too large.
1260  // FIXUPTYPE==2 models a local injection of baryons/energy with momentum conserved and energy-momentum conserved if mass injected. Injection will slow flow. Essentially there is an ad hoc conversion of kinetic/thermal energy into mass energy.
1261 
1262  // compute original conserved quantities
1263  failreturn=get_state(prmhd,ptrgeom,&q);
1264  if(failreturn>=1) dualfprintf(fail_file,"get_state(1) failed in fixup.c, why???\n");
1265  failreturn=primtoU(UNOTHING,prmhd,&q,ptrgeom,U, NULL);
1266  if(failreturn>=1) dualfprintf(fail_file,"primtoU(1) failed in fixup.c, why???\n");
1267 
1268  // store original U
1269  PLOOP(pliter,pl) U0[pl]=U[pl];
1270 
1271  // get change in primitive quantities
1272  PALLLOOP(pl) dprmhd[pl]=0.0; // default
1273  // use ZAMO velocity as velocity of inserted fluid
1274  PALLLOOP(pl) if(pl==RHO || pl==UU || pl==URAD0){ dprmhd[pl]=prmhdnew[pl]-prmhd[pl];}
1275  set_zamo_velocity(WHICHVEL,ptrgeom,dprmhd);
1276 
1277  // get change in conserved quantities
1278  failreturn=get_state(dprmhd,ptrgeom,&dq);
1279  failreturn=primtoU(UNOTHING,dprmhd,&dq,ptrgeom,dU, NULL);
1280  if(failreturn>=1) dualfprintf(fail_file,"primtoU(2) failed in fixup.c, why???\n");
1281 
1282 
1283  if(FIXUPTYPE==1){
1284  // then done, dU is right
1285  }
1286  else if(FIXUPTYPE==2){
1287  // then don't allow momentum to change regardless of meaning for implied rho,u
1288  dU[U1]=dU[U2]=dU[U3]=0.0;
1289  if(URAD0>=0) dU[URAD0]=dU[URAD1]=dU[URAD2]=dU[URAD3]=0.0;
1290 
1291  pl=UU;
1292  if ( checkfl[pl]&&(prfloor[pl] > prmhd[pl] || prceiling[pl] < prmhd[pl]) ){
1293  // then must change dU[UU]
1294  }
1295  else dU[UU]=0.0; // if only mass added, then no change needed to energy-momentum
1296 
1297 
1298  }
1299 
1300  // get final new conserved quantity
1301  PALLLOOP(pl) U[pl]+=dU[pl];
1302  // except, if fixed-up u_g or rho because <0, then just set entropy.
1303  // If u_g>0 and rho>0, then assume entropy adjustment also ok.
1304  // if((prmhd[UU]<=0.0 || prmhd[RHO]<=0.0) && ENTROPY>0) U[ENTROPY] = U0[ENTROPY];
1305  // assume this adjustment is energy-only based.
1306  // must do this because otherwise if u_g<0 or rho<0, then entropy is ill-defined, and here assume floor always activated related to too small u_g or rho so that entropy would be badly defined or ill-defined.
1307  if(ENTROPY>=0) U[ENTROPY] = U0[ENTROPY];
1308 
1309 
1310  // pr finally changes here
1311  // get primitive associated with new conserved quantities
1312  oldmhdpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
1313  oldradpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
1314 
1315  int showmessages=0; // messages not important if fixup doens't work, unless debugging.
1316  int allowlocalfailurefixandnoreport=1;
1317  int eomtype=EOMDEFAULT;
1318  FTYPE dissmeasure=-1.0; // assume energy try ok
1319  int whichcap=CAPTYPEBASIC;
1320  int whichmethod=MODEDEFAULT;
1321  int modprim=0;
1322  int checkoninversiongas=CHECKONINVERSION;
1323  int checkoninversionrad=CHECKONINVERSIONRAD;
1324 
1325  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
1326  if(0){
1327  newtonstats.nstroke=newtonstats.lntries=0;
1328  }
1329  else{
1331  // be quick about checking this
1332  newtonstats.nstroke=newtonstats.lntries=0;
1333  // set inputs for errors, maxiters, etc.
1334 #define IMPTRYCONVCONSTFORFX (1E-6)
1335 #define IMPOKCONVCONSTFORFX (1E-4)
1336 #define IMPALLOWCONVCONSTFORFX (1E-3)
1337 #define IMPMAXITERFORFX (10)
1338  newtonstats.tryconv=1E-2*MAX(IMPTRYCONVCONSTFORFX,IMPOKCONVCONSTFORFX);
1339  newtonstats.tryconvultrarel=1E-2*MAX(IMPTRYCONVCONSTFORFX,IMPOKCONVCONSTFORFX);
1340  newtonstats.extra_newt_iter=1;
1341  newtonstats.extra_newt_iter_ultrarel=2;
1342  newtonstats.mintryconv=IMPALLOWCONVCONSTFORFX;
1343  newtonstats.maxiter=IMPMAXITERFORFX;
1344  //
1345  }
1346  // dualfprintf(fail_file,"BEFORE FIXUPUTOPRIMGEN\n");
1347  failreturn=Utoprimgen(showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep,&eomtype,whichcap,whichmethod,modprim,OTHERUTOPRIM,UNOTHING,U,&q, ptrgeom,dissmeasure,prmhd,prmhd,&newtonstats);
1348  // dualfprintf(fail_file,"AFTER FIXUPUTOPRIMGEN\n");
1349  // have to add since takes effort.s
1350  nstroke+=newtonstats.nstroke; newtonstats.nstroke=newtonstats.lntries=0;
1351 
1352  // KORALNOTEMARK: Only changing floor related to MHD fluid so far, so no check on failure of radiation inversion.
1353  badinversion = (failreturn>=1 || IFUTOPRIMFAIL(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)));
1354 
1355  static long long int utoprimgenfixup=0,utoprimgenfixupbad=0;
1356  utoprimgenfixup++;
1357  if(badinversion) utoprimgenfixupbad++;
1358  if(debugfail>=2) if(utoprimgenfixup%totalzones==0) dualfprintf(fail_file,"UTOPRIMGENFIXUP: %lld (bad=%lld) : %ld %d\n",utoprimgenfixup,utoprimgenfixupbad,nstep,steppart);
1359 
1360 
1361  if(badinversion){
1362  if(debugfail>=2) dualfprintf(fail_file,"Utoprimgen failed in fixup.c");
1363  // if problem with Utoprim, then just modify primitive quantities as normal without any special constraints
1364  PALLLOOP(pl){
1365  prmhd[pl]=prmhdnew[pl];
1366  }
1367  }
1368 
1369  // in any case, this is not normal inversion procedure, so clear the flags
1370  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=oldmhdpflag;
1371  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=oldradpflag;
1372 
1373 #endif
1374 
1375 
1376  // get min or max of comoving and ZAMO frame versions of densities
1377  // generally trying to keep atmosphere non-relativistic
1378  // pl=RHO; prmhd[pl]=MIN(prmhd[pl],prmhdnew[pl]);
1379  // get larger of rho
1380  if(RHO>=0){ pl=RHO; prmhd[pl]=MAX(prmhd[pl],prmhdnew[pl]);}
1381  // get smallest of two
1382  if(UU>=0){ pl=UU; prmhd[pl]=MIN(prmhd[pl],prmhdnew[pl]);}
1383  if(URAD0>=0){ pl=URAD0; prmhd[pl]=MIN(prmhd[pl],prmhdnew[pl]);}
1384 
1385 
1386  }// end if didchangeprim
1387 
1388  }// end if cold or hot GRMHD
1389 
1390 
1391 
1392 
1394  //
1395  // since inflow check is on boundary values, no need for inflow check here
1396  //
1398 
1399 
1401  //
1402  // account for primitive changes
1403  //
1405  if(didchangeprim&&FLOORDIAGS){// FLOORDIAGS includes fail diags
1406  int docorrectucons2=(DOENOFLUX != NOENOFLUX);
1407  int doingmhdfixup=1;
1408  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
1409  // dualfprintf(fail_file,"FLOORACTBEFORE: steppart=%d nstep=%ld\n",steppart,nstep);
1410  // }
1411 
1412  PFTYPE *lpflag,*lpflagrad;
1413  lpflag=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
1414  lpflagrad=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
1415 
1416  if(*lpflag>UTOPRIMNOFAIL || IFUTOPRIMRADFAIL(*lpflagrad)){
1417  // by this point, pr0 or prdiag are not necessarily consistent with ucons, which if finalstep=1 is the final conserved quantity. This occurs when no implicit solution and no explicit inversion. Happens when (e.g.) U[RHO]<0.
1418  FTYPE Uievolve[NPR];
1419  PLOOP(pliter,pl) Uievolve[pl] = ucons[pl];
1420  diag_fixup_Ui_pf(docorrectucons2, Uievolve, prmhd, ptrgeom, finalstep,COUNTFLOORACT,NULL);
1421  }
1422  else{
1423  // if no failure, then fixup_utoprim won't be called or do diagnostics, so floor will be preserved and so do accounting here.
1424  diag_fixup(docorrectucons2,prdiag, prmhd, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTFLOORACT);
1425  }
1426 
1427 
1428 
1429 
1430  // now prdiag=prmhd as far as diag_fixup() is concerned, so next changes are new changes (i.e. don't cumulative w.r.t. pr0 multiple times, since that (relative to prmhd each time) would add each prior change to each next change)
1431  // PALLLOOP(pl) prdiag[pl]=prmhd[pl];
1432  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
1433  // dualfprintf(fail_file,"FLOORACTAFTER: steppart=%d nstep=%ld\n",steppart,nstep);
1434  // }
1435  }
1436 
1437 
1438 
1439 
1440 
1441 
1442  // assume once we go below floor, all hell will break loose unless we calm the storm by shutting down this zone's relative velocity
1443  // normal observer velocity
1444  // i.e. consider this a failure
1445  //GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)= 1;
1446 
1447 
1449  //
1450  // now keep track of modified primitives via conserved quantities
1451  //
1453  if(didchangeprim){
1454 
1456  //
1457  // Assign final primitives
1458  //
1460 
1461  PALLLOOP(pl) pr[pl]=prmhd[pl];
1462 
1463  // SUPERGODMARK: only doing rest-mass density here for now. Still account for YFL2-5 via finalstep==1 source injection, but sub-steps only then handle fluxes for YFL2-5 currently unless add how conserved quantities changed here. In any case, this is estimate for finalstep actual ucons vs. Uf(pf) changes.
1464  if(DOYFL){
1465  FTYPE drho=(pr[RHO]-pr0[RHO]);
1466  if(DOYFL==1){
1467  pr[YFL1] = (pr0[YFL1]*pr0[RHO] + drho)/pr[RHO];// have floor set new floor scalar fraction. Adds mass at same velocity for FIXUPTYPE==0
1468  if(pr[YFL1]<0.0) pr[YFL1]=0.0;
1469  if(pr[YFL1]>1.0) pr[YFL1]=1.0;
1470  }
1471  else if(DOYFL==2){
1472  pr[YFL1] = pr0[YFL1] + drho;
1473  if(pr[YFL1]<SMALL) pr[YFL1]=SMALL;
1474  if(pr[YFL1]>pr[RHO]) pr[YFL1]=pr[RHO];
1475  }
1476 
1477 
1478  if(DOYFL==2&&0){
1479  // also iterate on other YFLx's
1480  struct of_state qnew;
1481  get_state(pr,ptrgeom,&qnew);
1482  FTYPE Unew[NPR];
1483  primtoU(UNOTHING,pr,&qnew,ptrgeom,Unew, NULL);
1484 
1485  struct of_state q0;
1486  get_state(pr0,ptrgeom,&q0);
1487  FTYPE U0[NPR];
1488  primtoU(UNOTHING,pr0,&q0,ptrgeom,U0, NULL);
1489 
1490  if(YFL2>=0) pr[YFL2]+= -(Unew[UU]-U0[UU])/qnew.ucon[TT];
1491  if(YFL3>=0) pr[YFL3]+= +(Unew[U3]-U0[U3])/qnew.ucon[TT];
1492  if(YFLADDRADTOGAS){
1493  if(YFL2>=0) pr[YFL2]+= -(Unew[URAD0]-U0[URAD0])/qnew.uradcon[TT];
1494  if(YFL3>=0) pr[YFL3]+= +(Unew[URAD3]-U0[URAD3])/qnew.uradcon[TT];
1495  }
1496 
1497  if(YFL4>=0){
1498  pr[YFL4]+= -(Unew[URAD0]-U0[URAD0])/qnew.uradcon[TT];
1499  if(pr[YFL4]<ERADLIMIT) pr[YFL4]=ERADLIMIT;
1500  }
1501  if(YFL5>=0) pr[YFL5]+= (Unew[URAD3]-U0[URAD3])/qnew.uradcon[TT];
1502  }
1503  }
1504 
1505 
1506 #if(0)
1507 
1508  //
1509  // now ensure primitive and conserved consistent for RK3 and other methods that use Uf
1510  // assumes "ucons" is utoinvert in advance.c so it's uf or utempcum when necessary as associated with inversion (internal implicit or external).
1511  //
1513  // here's where we correct ucons
1514  docorrectucons=1;
1515  struct of_state qnew;
1516  get_state(pr,ptrgeom,&qnew);
1517 
1518  primtoU(UEVOLVE,pr,&qnew,ptrgeom,ucons, NULL);
1519 #endif
1520 
1521  return(-1); // -1 means made changes
1522 
1523  }
1524 
1525 
1526  if(uconsinput!=NULL && docorrectucons){
1527  // copy over ucons result in case changed.
1528  PLOOP(pliter,pl){
1529  // if staggered field, avoid modifying field since at FACEs, not CENT where pr lives.
1530  if(BPL(pl)==0 && FLUXB==FLUXCTSTAG || FLUXB==FLUXCTTOTH){
1531  uconsinput[pl] = ucons[pl];
1532  }
1533  }
1534  }
1535 
1536 
1537  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
1538  // struct of_state qb;
1539  // get_state(pr,ptrgeom,&qb);
1540  // FTYPE ub[NPR],ubabs[NPR];
1541  // int uutype=UDIAG;
1542  // primtoU(uutype,pr,&qb,ptrgeom,ub,ubabs);
1543  // dualfprintf(fail_file,"URHOINFIXUPU1ZONE=%21.15g\n",ub[RHO]*dx[1]*dx[2]*dx[3]);
1544  // }
1545 
1546 
1547 
1548  return(0);
1549 }
1550 
1551 
1552 // number of vote checks per zone
1553 #define MAXVOTES 8
1554 
1555 #define NUMCHECKS 2
1556 #define ISGAMMACHECK 0
1557 #define ISUUCHECK 0
1558 
1567 int fixup_checksolution(int stage, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],int finalstep)
1568 {
1569  // int inboundloop[NDIM];
1570  // int outboundloop[NDIM];
1571  // int innormalloop[NDIM];
1572  // int outnormalloop[NDIM];
1573  // int inoutlohi[NUMUPDOWN][NUMUPDOWN][NDIM];
1574  // int riin,riout,rjin,rjout,rkin,rkout;
1575  // int dosetbc[COMPDIM*2];
1576  // int ri;
1577  // int boundvartype=BOUNDINTTYPE;
1578  // extra memory
1579  FTYPE (*gammacheck)[NSTORE2][NSTORE3][NPR];
1580  extern void get_advance_startendindices(int *is,int *ie,int *js,int *je,int *ks,int *ke);
1581  int is,ie,js,je,ks,ke;
1582 
1584  //
1585  // setup memory space for gammacheck
1586  //
1588 
1589  // use UU space for holding \gamma
1590  gammacheck = GLOBALPOINT(ptemparray); // should be ok to use since fixup_checksolution() not called inside higher order or EOS or in fixup_utoprim() where also used
1591 
1592 
1594  //
1595  // set bound loop
1596  //
1598  // set_boundloop(boundvartype, inboundloop,outboundloop,innormalloop,outnormalloop,inoutlohi, &riin, &riout, &rjin, &rjout, &rkin, &rkout, dosetbc);
1599  // +-1 extra so can do check
1606 
1607 
1608 
1609 
1611  //
1612  // determine gamma to be used
1613  //
1615  // LOOPXalldir{
1617 #pragma omp parallel // don't need full (i.e. don't need EOS here)
1618  {
1619  int i,j,k;
1620  FTYPE ucon[NDIM],others[NUMOTHERSTATERESULTS];
1621  FTYPE qsq;
1622  struct of_geom geomdontuse;
1623  struct of_geom *ptrgeom=&geomdontuse;
1624  OPENMP3DLOOPVARSDEFINE; OPENMP3DLOOPSETUP(is,ie,js,je,ks,ke);
1625 
1626 
1627 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1629  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1630 
1631  // if(1|| (GLOBALMACP0A1(pflag,i,j,k,FLAGBSQORHO)||GLOBALMACP0A1(pflag,i,j,k,FLAGBSQOU))&&(IFUTOPRIMFAILORFIXED(GLOBALMACP0A1(pflag,i,j,k,FLAGUTOPRIMFAIL)))){
1632  if(1){
1633  get_geometry(i,j,k,CENT,ptrgeom);
1634 
1635 #if(WHICHVEL==VELREL4)
1636  MYFUN(gamma_calc(MAC(pv,i,j,k),ptrgeom,&MACP0A1(gammacheck,i,j,k,UU),&qsq),"fixup_checksolution: gamma calc failed\n","fixup.c",1);
1637 #else
1638  if (ucon_calc(MAC(pv,i,j,k), ptrgeom, ucon, others) >= 1) FAILSTATEMENT("fixup.c:fixup_checksolution()", "ucon_calc()", 1);
1639  MACP0A1(gammacheck,i,j,k,UU)=ucon[TT];
1640 #endif
1641  }// end if 1
1642  }// end 3D LOOP
1643  }// end parallel region
1644 
1645 
1646 
1647 
1648 
1649 
1651  //
1652  // see if percent differences (actually factors) are too large
1653  //
1655 
1657 #pragma omp parallel // don't need copyin, doesn't currently use global non-array vars
1658  {
1659  int i,j,k;
1660  int l;
1661  FTYPE percdiff[NUMCHECKS][MAXVOTES];
1662  int vote[NUMCHECKS];
1663  int numvotes[NUMCHECKS];
1664  int checkcondition[NUMCHECKS];
1665  int checki;
1666 
1668 
1669 
1670 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1672  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1673 
1674 
1675 
1676  // doesn't need bound of pflag since don't check pflag of surrounding values (assumes if comparing with failure point, failure point is reasonable afterwards if before)
1677  // if(1 || (GLOBALMACP0A1(pflag,i,j,k,FLAGBSQORHO)||GLOBALMACP0A1(pflag,i,j,k,FLAGBSQOU))&&(IFUTOPRIMFAILORFIXED(GLOBALMACP0A1(pflag,i,j,k,FLAGUTOPRIMFAIL)))){// if b^2/{rho,u}\gg 1 and not failure already, check if solution is reasonable
1678 
1679  checkcondition[ISGAMMACHECK]=(MACP0A1(gammacheck,i,j,k,UU)>=2.0);
1680  checkcondition[ISUUCHECK]=1;
1681 
1682  // use fabs in case gamma<0 or especially if u<zerouuperbaryon*prim[RHO] that can easily happen
1683  if(checkcondition[ISGAMMACHECK]){
1684  percdiff[ISGAMMACHECK][0]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,i,jp1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,i,jp1mac(j),k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1685  percdiff[ISGAMMACHECK][1]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,i,jm1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,i,jm1mac(j),k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1686  percdiff[ISGAMMACHECK][2]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),j,k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,ip1mac(i),j,k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1687  percdiff[ISGAMMACHECK][3]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,im1mac(i),j,k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,im1mac(i),j,k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1688 
1689  percdiff[ISGAMMACHECK][4]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),jp1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,ip1mac(i),jp1mac(j),k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1690  percdiff[ISGAMMACHECK][5]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),jm1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,ip1mac(i),jm1mac(j),k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1691  percdiff[ISGAMMACHECK][6]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),jp1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,ip1mac(i),jp1mac(j),k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1692  percdiff[ISGAMMACHECK][7]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,im1mac(i),jm1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(gammacheck,im1mac(i),jm1mac(j),k,UU)/MACP0A1(gammacheck,i,j,k,UU)) : -1;
1693  }
1694 
1695  if(checkcondition[ISUUCHECK]){
1696  percdiff[ISUUCHECK][0]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,i,jp1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,i,jp1mac(j),k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1697  percdiff[ISUUCHECK][1]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,i,jm1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,i,jm1mac(j),k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1698  percdiff[ISUUCHECK][2]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),j,k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,ip1mac(i),j,k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1699  percdiff[ISUUCHECK][3]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,im1mac(i),j,k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,im1mac(i),j,k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1700 
1701  percdiff[ISUUCHECK][4]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),jp1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,ip1mac(i),jp1mac(j),k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1702  percdiff[ISUUCHECK][5]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),jm1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,ip1mac(i),jm1mac(j),k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1703  percdiff[ISUUCHECK][6]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,ip1mac(i),jp1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,ip1mac(i),jp1mac(j),k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1704  percdiff[ISUUCHECK][7]=(IFUTOPRIMNOFAILORFIXED(GLOBALMACP0A1(pflag,im1mac(i),jm1mac(j),k,FLAGUTOPRIMFAIL))) ? fabs(MACP0A1(pv,im1mac(i),jm1mac(j),k,UU)/MACP0A1(pv,i,j,k,UU)) : -1;
1705  }
1706 
1708  //
1709  // determine how many votes
1710  //
1712  for(checki=0;checki<NUMCHECKS;checki++){
1713  vote[checki]=0;
1714  numvotes[checki]=0;
1715  }
1716  for(l=0;l<MAXVOTES;l++){
1717  // No vote for failed zones
1718  if(checkcondition[ISGAMMACHECK] && percdiff[ISGAMMACHECK][l]>=0.0){
1719  if( (fabs(percdiff[ISGAMMACHECK][l])>GAMMAPERCDIFFMAX)||(fabs(percdiff[ISGAMMACHECK][l])<1.0/GAMMAPERCDIFFMAX) ) vote[ISGAMMACHECK]++;
1720  numvotes[ISGAMMACHECK]++;
1721  }
1722  if(checkcondition[ISUUCHECK] && percdiff[ISUUCHECK][l]>=0.0){
1723  if((DOEVOLVEUU)&& ((fabs(percdiff[ISUUCHECK][l])>UPERCDIFFMAX)||(fabs(percdiff[ISUUCHECK][l])<1.0/UPERCDIFFMAX)) ) vote[ISUUCHECK]++;
1724  numvotes[ISUUCHECK]++;
1725  }
1726  }
1727 
1729  //
1730  // Use majority rule: This allows shock fronts, but no faster members.
1731  // Don't include failures in voting process (either count or total voting)
1732  // > is used in case degenerate condition 0>0 so if no votes and no total, then do nothing
1733  //
1735  checki=ISGAMMACHECK;
1736  if(checkcondition[checki] && (vote[checki]>numvotes[checki]*0.5)){
1737  // then majority rules
1738  // stderrfprintf("caught one-0: %d %d\n",i,j);
1739  GLOBALMACP0A1(pflag,i,j,k,FLAGUTOPRIMFAIL)=UTOPRIMFAILGAMMAPERC;
1740  }
1741  checki=ISUUCHECK;
1742  if(checkcondition[checki] && (vote[checki]>numvotes[checki]*0.5)){
1743  // then majority rules
1744  // stderrfprintf("caught one-1: %d %d\n",i,j);
1745  GLOBALMACP0A1(pflag,i,j,k,FLAGUTOPRIMFAIL)=UTOPRIMFAILUPERC;
1746  }
1747 
1748  }// end COMPZLOOP
1749  }// end parallel region
1750 
1751  return(0);
1752 }
1753 
1754 
1755 
1756 
1757 
1758 
1759 
1760 
1761 
1762 
1763 
1764 
1765 
1766 #if(MPIEQUALNONMPI==1)
1767 #define ORDERINDEPENDENT 1 // no choice
1768 // whether fixup_utoprim should be order-independent or not
1769 #else
1770 #define ORDERINDEPENDENT 1 // NO choice anymore, with fixup done before assigning initial D0, gamma, etc.
1771 #endif
1772 
1773 // whether to do specific chosen points for averages or do maximal average
1774 #define GENERALAVERAGE 1
1775 
1776 // whether to conserve D when averaging (uses original D to keep D constant -- less problematic compared to how used in limit_gamma() where original \gamma might be quite large)
1777 // This is probably not useful
1778 // More useful to use conserved D from unew as reference D0 so particle mass really conserved -- and this is ok compared to limit_gamma since newly averaged 4-velocity will not imply a large \gamma (unless averaging nearly failed regions!)
1779 // Also, during failure, can't assume mass can be so easily conserved and D might be bad
1780 // So disable for now
1781 // enable for finalstep for YFL, but for RHO causes high gamma fixed in regions, so disable for that
1782 #define DO_CONSERVE_D_INFAILFIXUPS (0&&finalstep==1 && (SCALARPL(pl))) // not pl==RHO
1783 
1784 #define HANDLEUNEG 0
1785 // seems to keep failing with this, so probably treating u<zerouuperbaryon*prim[RHO] like failure is better idea
1786 // 0: treat as full failure
1787 // 1: treat as floor issue
1788 
1789 #define HANDLERHONEG 0
1790 // seems to keep failing with this, so probably treating rho<0 like failure is better idea
1791 // 0: treat as full failure
1792 // 1: treat as floor issue
1793 
1794 #define HANDLERHOUNEG 0
1795 // seems to keep failing with this, so probably treating rho<0 like failure is better idea
1796 // 0: treat as full failure
1797 // 1: treat as floor issue
1798 
1799 
1802 int fixup_utoprim(int stage, FTYPE (*pv)[NSTORE2][NSTORE3][NPR], FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep)
1803 {
1804  FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR];
1805  extern void get_advance_startendindices(int *is,int *ie,int *js,int *je,int *ks,int *ke);
1806  int is,ie,js,je,ks,ke;
1807 
1808 
1809 
1810 
1811  // this average only works if using 4 velocity since only then guaranteed solution is good after interpolation
1812  if(WHICHVEL==VEL3) return(0); // just stick with static, best can do
1813  if(EOMTYPE==EOMFFDE || EOMTYPE==EOMFFDE2) return(0); // nothing to do
1814 
1815 
1816 
1817 
1818  if(ORDERINDEPENDENT){
1819  // then on the right-side of equations should appear ptoavg and on left side pv
1820  // put another way, ptoavg contains constant thing never to be modified. Usually then, pv is never used except to have something assigned to it, but could be conditions and such post-assignment that modifies the assignment but NOT the behavior of the routine otherwise.
1821  ptoavg=GLOBALPOINT(ptemparray);
1822  // ptemparray is used since in step_ch.c not needed after each advance()
1823  // ptemparray is template for values used to fixup failures.
1824  // In fixup-loop below, only change/fixup pv, not prc. Otherwise order-dependent and not MPI friendly
1825  // ptoavg is only used for surrounding zones used to fixup local zone
1826  //LOOPXalldir
1827 
1828  get_inversion_startendindices(Uconsevolveloop,&is,&ie,&js,&je,&ks,&ke);
1829 
1830  // +-NUMPFLAGBNDx extra so can do check
1831  is += -NUMPFLAGBND1;
1832  ie += +NUMPFLAGBND1;
1833  js += -NUMPFLAGBND2;
1834  je += +NUMPFLAGBND2;
1835  ks += -NUMPFLAGBND3;
1836  ke += +NUMPFLAGBND3;
1837 
1839  copy_3dnpr(is,ie,js,je,ks,ke,pv,ptoavg); // GODMARK: Won't PLOOP be PALLLOOP here, so ok?
1840  }
1841  else ptoavg=pv;
1842 
1844  //
1845  // Save original pflag before changed. This ensures thread-safety
1846  //
1848 
1849  // shouldn't modify pflagfailorig once inside parallel region below
1850  // Should only modify final (true) pflag value
1851  // only copies fail flags
1852  copy_3dpftype_special_fullloop(GLOBALPOINT(pflag),GLOBALPOINT(pflagfailorig));
1853 
1854 
1855 
1856 
1857 
1859  //
1860  // first check for bad solutions and try to fix based upon average surrounding solution
1861  //
1863 
1865 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOM // accounting requires state stuff
1866  {
1867  int i,j,k,pl,pliter;
1868  FTYPE gamma,alpha,vsq,ucon[NDIM],others[NUMOTHERSTATERESULTS];
1869  FTYPE qsq;
1870  FTYPE pr0[NPR];
1871  PFTYPE mhdlpflag,radlpflag;
1872  int fixedmhd,fixedrad;
1873  int startpl,endpl;
1874  FTYPE ftemp;
1875  FTYPE D0;
1876  //
1877  int limitedgamma;
1878  int nogood;
1879  struct of_geom geomdontuse;
1880  struct of_geom *ptrgeom=&geomdontuse;
1881  int fixingmhd,fixingrad;
1882  int limitgammamhd,limitgammarad;
1883 
1884 
1886 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1888  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1889 
1890 
1891 
1892  // get failure flag
1893  mhdlpflag=GLOBALMACP0A1(pflagfailorig,i,j,k,FLAGUTOPRIMFAIL);
1894  radlpflag=GLOBALMACP0A1(pflagfailorig,i,j,k,FLAGUTOPRIMRADFAIL);
1895 
1896  // assume not fixing anything
1897  fixingmhd=IFUTOPRIMFAIL(mhdlpflag);
1898  fixingrad=IFUTOPRIMRADFAIL(radlpflag); // not just a hard failure, but some softish ones too
1899 
1900 
1901 
1902  if(IFUTOPRIMFAILFIXED(mhdlpflag) && IFUTOPRIMFAILFIXED(radlpflag)){ // IF BOTH MHD AND RAD FIXED-UP ELSEWHERE
1904  //
1905  // see if utoprim() previously fixed so can do diagnostics
1906  // only do accounting
1907  //
1909 
1910  // set pre-fixed primitives
1911  PALLLOOP(pl) pr0[pl]=MACP0A1(ptoavg,i,j,k,pl);
1912  get_geometry(i,j,k,CENT,ptrgeom);
1913 
1915  //
1916  // ACCOUNTING (static or average)
1917  //
1919  fixuputoprim_accounting(i, j, k, mhdlpflag, radlpflag, 0, 0, GLOBALPOINT(pflag),pv,ptoavg, ptrgeom, pr0, ucons, finalstep);
1920 
1921 
1922  }
1923  else if(fixingmhd || fixingrad){
1924 
1925 
1926 
1927 
1928 
1929  if(fixingmhd){
1930 
1933  //
1934  // see if MHD utoprim() failed
1935  //
1938 
1939  fixedmhd=0; // assume not fixed yet
1940 
1941  // set pre-fixed primitives
1942  // put back inside "if" when not superdebugging since wasteful of cpu
1943  PALLLOOP(pl) pr0[pl]=MACP0A1(ptoavg,i,j,k,pl);
1944  get_geometry(i,j,k,CENT,ptrgeom);
1945 
1946 
1948  //
1949  // Check if want to average
1950  //
1951  // only modified if doing some kind of averaging, else static since already kept old value in inversion method
1952  //
1955 
1957  //
1958  // choose which range of quantities to average
1959  // Doesn't include any floor scalars (e.g. YFLx) presumed to be forced as fully conservative post-adjusted ucon[TT] unlike (normally) evolved density
1960  //
1962  // field is evolved fine, so only average non-field
1963  if(mhdlpflag==UTOPRIMFAILRHOUNEG && HANDLERHOUNEG==1){
1964  startpl=RHO;
1965  endpl=UU;
1966  }
1967  else if(mhdlpflag==UTOPRIMFAILU2AVG1 || mhdlpflag==UTOPRIMFAILU2AVG2 || mhdlpflag==UTOPRIMFAILU2AVG1FROMCOLD || mhdlpflag==UTOPRIMFAILU2AVG2FROMCOLD || mhdlpflag==UTOPRIMFAILUPERC || mhdlpflag==UTOPRIMFAILUNEG && (HANDLEUNEG==1) ){
1968  startpl=UU;
1969  endpl=UU;
1970  }
1971  else if(mhdlpflag==UTOPRIMFAILRHONEG && HANDLERHONEG==1){
1972  startpl=RHO;
1973  endpl=RHO;
1974  }
1975  else if(mhdlpflag==UTOPRIMFAILURHO2AVG1FROMFFDE){
1976  startpl=RHO;
1977  endpl=UU;
1978  // SUPERGODMARK: should also average v along v.B
1979  }
1980  else{
1981  // then presume inversion failure with no solution or assuming rho<=0 or u<=zerouuperbaryon*prim[RHO] is bad inversion if HANDLE?NEG==0
1982  startpl=RHO;
1983  endpl=NPR-1;
1984  }
1985 
1986 
1987 
1988 
1989 
1990 
1991 
1993  //
1994  // other kinds of failures not caught by above (inversion convergence type failures)
1995  //
1997  if(fixedmhd==0){
1998 
1999 
2001  //
2002  // fix using average of surrounding good values, if they exist
2003  //
2005  nogood=0;
2006  int doingmhd=1;
2007 #if(GENERALAVERAGE==1)
2008  int useonlynonfailed=1;
2009  int maxnumbndtotry=MAXNUMPFLAGBND; // choice smaller or equal to MAXNUMPFLAGBND
2010  int numbndtotry;
2011  // TODOMARK: could also do multi-pass fixup_utoprim() with BCs done as squeeze in on failure region from outside, in case region is not caught by this.
2012  for(numbndtotry=1;numbndtotry<=maxnumbndtotry;numbndtotry++){
2013  nogood=general_average(useonlynonfailed,numbndtotry,maxnumbndtotry,startpl, endpl, i, j, k, doingmhd, mhdlpflag, radlpflag, GLOBALPOINT(pflagfailorig) ,pv,ptoavg,ptrgeom);
2014  if(nogood==0) break; // then success before using any more points
2015  }
2016 #else
2017  nogood=simple_average(startpl,endpl,i,j,k, doingmhd, GLOBALPOINT(pflagfailorig) ,pv,ptoavg);
2018 #endif
2019 
2020 
2021  if(nogood){
2023  //
2024  // fixup negative densities (if no good case)
2025  //
2027  fixup_negdensities(EOMSETMHD, &fixedmhd, startpl, endpl, i, j, k, mhdlpflag, pv,ptoavg, ptrgeom, pr0, ucons, finalstep);
2028 
2029  if(fixedmhd==1 && (startpl<=RHO && endpl<=UU)){
2030  // assume success for densities, so no longer nogood.
2031  nogood=0;
2032  }
2033 
2034  if(fixedmhd==1 && (startpl<=RHO && endpl>=U1)){
2035  // then fixup but only changed densities, so still need to process non-densities
2036  startpl=U1; // start at U1 (first velocity) and finish at same ending if was ending on some velocity
2037  fixedmhd=0; // then reset fixedmhd->0 so can still modify these remaining quantities -- otherwise v^i would be unchanged even if wanted to average that out for (e.g.) negative density results for inversions.
2038  }
2039  }
2040 
2042  //
2043  // If no good surrounding value found, then average bad values in some way
2044  //
2046  if(nogood){
2047  // dualfprintf(fail_file,"fixupnogood: mhd %d %d %d : %d %d\n",i,j,k,startpl,endpl);
2048  fixup_nogood(startpl, endpl, i, j, k, doingmhd, mhdlpflag, radlpflag, pv,ptoavg, pbackup, ptrgeom);
2049  }
2050 
2051 
2052 
2054  //
2055  // Things to do only if modifying velocity
2056  //
2058  if(startpl<=U1 && endpl>=U3){
2059 
2060 #if(WHICHVEL==VELREL4)
2061 
2062  //
2063  // check gamma to so calibrate new gamma to no larger than previous gamma
2065  MYFUN(gamma_calc(MAC(ptoavg,i,j,k),ptrgeom,&gamma,&qsq),"fixup_utoprim: gamma calc failed\n","fixup.c",1);
2066  if (ucon_calc(MAC(ptoavg,i,j,k), ptrgeom, ucon, others) >= 1) FAILSTATEMENT("fixup.c:utoprimfail_fixup()", "ucon_calc()", 1);
2067  // alpha = 1. / sqrt(-ptrgeom->gcon[GIND(0,0)]);
2068  alpha = ptrgeom->alphalapse;
2069  vsq = 1. - 1. / (alpha * alpha * ucon[0] * ucon[0]);
2070 
2071  limitedgamma=0;
2072  if(gamma>GAMMAMAX){
2073  limitedgamma=1;
2074  if(debugfail>=2) dualfprintf(fail_file,"MHD: initial gamma: %21.15g, max: %21.15g, initial vsq: %21.15g\n",gamma,GAMMAMAX,vsq);
2075  // limit:
2076  gamma=GAMMAMAX;
2077  }
2078 #else
2079  limitedgamma=0;
2080  if (ucon_calc(MAC(ptoavg,i,j,k), ptrgeom, ucon,others) >= 1) FAILSTATEMENT("fixup.c:utoprimfail_fixup()", "ucon_calc()", 1);
2081 #endif
2082 
2083 
2085  //
2086  // check new gamma to make sure smaller than original (i.e. for pv, not original ptoavg)
2087  //
2089 
2090 #if(WHICHVEL==VELREL4)
2091  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2092  // dualfprintf(fail_file,"BEFORE IN FIXUPUTOPRIM LIMITGAMMA: finalstep=%d flag=%d\n",finalstep,mhdlpflag);
2093  // }
2094  if(limitgammamhd=limit_gamma(0,gamma,GAMMAMAXRAD,MAC(pv,i,j,k),MAC(ucons,i,j,k),ptrgeom,-1)>=1) FAILSTATEMENT("fixup.c:fixup()", "limit_gamma()", 2);
2095  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2096  // dualfprintf(fail_file,"AFTER IN FIXUPUTOPRIM LIMITGAMMA: finalstep=%d\n",finalstep);
2097  // }
2098 
2099  if(debugfail>=3){
2100  if(limitedgamma){
2101  // check gamma
2102  MYFUN(gamma_calc(MAC(pv,i,j,k),ptrgeom,&gamma,&qsq),"fixup_utoprim: gamma calc failed\n","fixup.c",2);
2103  dualfprintf(fail_file,"MHD: final gamma: %21.15g\n",gamma);
2104  }
2105  }
2106 #endif
2107 
2108  }// end if dealing with velocity
2109 
2110 
2111 
2113  //
2114  // Things to do only if modifying density (must come after modifying velocity that enters ucon[TT])
2115  //
2117  PLOOP(pliter,pl){
2118  if(pl==RHO || pl==YFL1 || pl==YFL2 || pl==YFL3){
2119  if(startpl<=pl && endpl>=pl){
2120 
2121 
2123 
2124  if(mhdlpflag==UTOPRIMFAILGAMMAPERC || 1){ // GODMARK: always doing it
2125 
2126  if (ucon_calc(MAC(ptoavg,i,j,k), ptrgeom, ucon, others) >= 1) FAILSTATEMENT("fixup.c:utoprimfail_fixup()", "ucon_calc()", 1);
2127 
2128  // Use D0 to constrain how changing u^t changes rho
2129  // GODMARK: Why not used evolved D=\rho_0 u^t from conserved quantity?
2130  // GODMARK: See fixup.c's limit_gamma() notes on why using conserved version of D not good to use
2131  // Here we ignore all conserved quantities and just ensure that D0 is conserved (close) to original value after averaging that assumes original value was reasonable
2132  if(finalstep==1){
2133  // this is not reasonable, because ignores any mass injection required during failure to make sense of solution
2134  FTYPE Unothing[NPR];
2135  UtoU(UEVOLVE,UNOTHING,ptrgeom,MAC(ucons,i,j,k),Unothing);
2136  D0 = Unothing[pl] ;
2137  }
2138  else{
2139  // This is probably not necessary or useful
2140  D0 = MACP0A1(ptoavg,i,j,k,pl)*ucon[TT];
2141  }
2142 
2144  //
2145  // constrain change in density so conserve particle number
2146  //
2148  if(D0>0.0 && pl==RHO || pl==YFL1 || pl==YFL2 || pl==YFL3){ // only makes sense if D0 implies positive density at least
2149  MACP0A1(pv,i,j,k,pl) = D0/ucon[TT];
2150  }
2151  }
2152  }
2153  }
2154  }
2155  }// end over density or scalars
2156 
2157 
2158 
2159 #if(0)
2160  // DEBUG problem of launch with pressureless stellar model collapse
2161  PALLLOOP(pl) dualfprintf(fail_file,"nstep=%ld steppart=%d :: i=%d j=%d k=%d pl=%d pv=%21.15g ptoavg=%21.15g\n",nstep,steppart,i,j,k,pl,MACP0A1(pv,i,j,k,pl),MACP0A1(ptoavg,i,j,k,pl));
2162 #endif
2163 
2164 
2165 
2166  } // end if fixedmhd==0
2167 
2168  }// end if not keeping static
2169  }// end if mhd failed
2170 
2171 
2172 
2173 
2174 
2175 
2176 
2177  if(fixingrad){ // RAD FAILED
2178 
2181  //
2182  // see if u2p_rad() failed in some way
2183  //
2186 
2187  fixedrad=0; // assume not fixedrad yet
2188 
2189  // set pre-fixedrad primitives
2190  // put back inside "if" when not superdebugging since wasteful of cpu
2191  PALLLOOP(pl) pr0[pl]=MACP0A1(ptoavg,i,j,k,pl);
2192  get_geometry(i,j,k,CENT,ptrgeom);
2193 
2194 
2196  //
2197  // Check if want to average
2198  //
2199  // only modified if doing some kind of averaging, else static since already kept old value in inversion method
2200  //
2203 
2205  //
2206  // choose which range of quantities to average
2207  //
2209  // field is evolved fine, so only average non-field
2210  if(radlpflag==UTOPRIMFAILU2AVG1 || radlpflag==UTOPRIMFAILU2AVG2 || radlpflag==UTOPRIMFAILU2AVG1FROMCOLD || radlpflag==UTOPRIMFAILU2AVG2FROMCOLD || radlpflag==UTOPRIMFAILUPERC || radlpflag==UTOPRIMFAILUNEG && (HANDLEUNEG==1) || radlpflag==UTOPRIMRADFAILERFNEG){
2211  startpl=PRAD0; // use as minimum for PRAD0 and average for PRAD1-PRAD3
2212  endpl=PRAD3;
2213  }
2214  else if(radlpflag==UTOPRIMRADFAILGAMMAHIGH){ // fixing gammarad so no constant high value from hitting ceiling on gammaradmax
2215  startpl=PRAD1;
2216  endpl=PRAD3;
2217  }
2218  else{
2219  // then presume inversion failure with no solution
2220  startpl=RHO;
2221  endpl=NPR-1;
2222  }
2223 
2224 
2225 
2226 
2227 
2229  //
2230  // other kinds of failures not caught by above (inversion convergence type failures)
2231  //
2233  if(fixedrad==0){
2234 
2235 
2237  //
2238  // fix using average of surrounding good values, if they exist
2239  //
2241  nogood=0;
2242  int doingmhd=0;
2243 #if(GENERALAVERAGE==1)
2244  int useonlynonfailed=1;
2245  int maxnumbndtotry=MAXNUMPFLAGBND; // choice smaller or equal to MAXNUMPFLAGBND
2246  int numbndtotry;
2247  for(numbndtotry=1;numbndtotry<=maxnumbndtotry;numbndtotry++){
2248  nogood=general_average(useonlynonfailed,numbndtotry,maxnumbndtotry,startpl, endpl, i, j, k, doingmhd, mhdlpflag, radlpflag, GLOBALPOINT(pflagfailorig) ,pv,ptoavg,ptrgeom);
2249  if(nogood==0) break; // then success before using any more points
2250  }
2251 #else
2252  nogood=simple_average(startpl,endpl,i,j,k, doingmhd, GLOBALPOINT(pflagfailorig) ,pv,ptoavg);
2253 #endif
2254 
2255 
2256  if(nogood && 0){ // avoid fixup_negdensities() because resets to ERADLIMIT
2258  //
2259  // fixup negative densities
2260  //
2262  fixup_negdensities(EOMSETRAD,&fixedrad, startpl, endpl, i, j, k, radlpflag, pv,ptoavg, ptrgeom, pr0, ucons, finalstep);
2263 
2264  if(fixedrad==1 && (startpl==URAD0 && endpl==URAD0)){
2265  // assume success for densities, so no longer nogood.
2266  nogood=0;
2267  }
2268  if(fixedrad==1 && (startpl<=URAD0 && endpl>=URAD1)){
2269  // then fixup but only changed densities, so still need to process non-densities
2270  startpl=URAD1; // start at U1 (first velocity) and finish at same ending if was ending on some velocity
2271  fixedrad=0; // then reset fixedmhd->0 so can still modify these remaining quantities -- otherwise v^i would be unchanged even if wanted to average that out for (e.g.) negative density results for inversions.
2272  }
2273  }
2274 
2275  // dualfprintf(fail_file,"Trying no good? nogood=%d\n",nogood);
2276 
2278  //
2279  // If no good surrounding value found, then average bad values in some way
2280  //
2282  if(1){ // should stay 1, see below.
2283  if(nogood){
2284  // dualfprintf(fail_file,"fixupnogood: rad %d %d %d : %d %d\n",i,j,k,startpl,endpl);
2285  fixup_nogood(startpl, endpl, i, j, k, doingmhd, mhdlpflag, radlpflag, pv,ptoavg, pbackup, ptrgeom);
2286  }
2287  }
2288  else{
2289  // normally assume u2p_rad() did ok local fixup if non-local fixup doesn't work out.
2290  // NO, reset failure to non-failure if ok local fixup. If here, want fixup even of radiation quantity, such as when implicit solver fails.
2291  }
2292 
2293  // if(MACP0A1(pv,i,j,k,URAD0)<1.5*ERADLIMIT){
2294  // dualfprintf(fail_file,"Why not fixed? %d %d %d: %21.15g err=%d\n",i,j,k,MACP0A1(pv,i,j,k,URAD0),radlpflag);
2295  // myexit(0);
2296  // }
2297 
2298 
2300  //
2301  // Things to do only if modifying radiation velocity
2302  //
2304  if(startpl<=PRAD1 && endpl>=PRAD3){
2305 
2306 #if(WHICHVEL==VELREL4)
2307 
2308  //
2309  // check gamma to so calibrate new gamma to no larger than previous gamma
2311  MYFUN(gamma_calc(&MACP0A1(ptoavg,i,j,k,URAD1-U1),ptrgeom,&gamma,&qsq),"fixup_utoprim: gamma calc failed\n","fixup.c",1);
2312  if (ucon_calc(&MACP0A1(ptoavg,i,j,k,URAD1-U1), ptrgeom, ucon, others) >= 1) FAILSTATEMENT("fixup.c:utoprimfail_fixup()", "ucon_calc()", 1);
2313  // alpha = 1. / sqrt(-ptrgeom->gcon[GIND(0,0)]);
2314  alpha = ptrgeom->alphalapse;
2315  vsq = 1. - 1. / (alpha * alpha * ucon[0] * ucon[0]);
2316 
2317  limitedgamma=0;
2318  if(gamma>GAMMAMAXRAD){
2319  limitedgamma=1;
2320  if(debugfail>=2) dualfprintf(fail_file,"RAD: initial gamma: %21.15g, max: %21.15g, initial vsq: %21.15g\n",gamma,GAMMAMAXRAD,vsq);
2321  // limit:
2322  gamma=GAMMAMAXRAD;
2323  }
2324 #else
2325  limitedgamma=0;
2326  if (ucon_calc(&MACP0A1(ptoavg,i,j,k,URAD1-U1), ptrgeom, ucon,others) >= 1) FAILSTATEMENT("fixup.c:utoprimfail_fixup()", "ucon_calc()", 1);
2327 #endif
2328 
2329 
2331  //
2332  // check new gamma to make sure smaller than original (i.e. for pv, not original ptoavg)
2333  //
2335 
2336 #if(WHICHVEL==VELREL4)
2337  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2338  // dualfprintf(fail_file,"BEFORE IN FIXUPUTOPRIM LIMITGAMMA2: finalstep=%d radlpflag=%d\n",finalstep,radlpflag);
2339  // }
2340  if(limitgammarad=limit_gamma(0,GAMMAMAX,gamma,MAC(pv,i,j,k),MAC(ucons,i,j,k),ptrgeom,-1)>=1) FAILSTATEMENT("fixup.c:fixup()", "limit_gamma()", 2);
2341  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2342  // dualfprintf(fail_file,"AFTER IN FIXUPUTOPRIM LIMITGAMMA2: finalstep=%d\n",finalstep);
2343  // }
2344 
2345  if(debugfail>=3){
2346  if(limitedgamma){
2347  // check gamma
2348  MYFUN(gamma_calc(&MACP0A1(pv,i,j,k,URAD1-U1),ptrgeom,&gamma,&qsq),"fixup_utoprim: gamma calc failed\n","fixup.c",2);
2349  dualfprintf(fail_file,"RAD: final gamma: %21.15g\n",gamma);
2350  }
2351  }
2352 #endif
2353 
2354  }// end if dealing with velocity
2355 
2356 
2357 
2359  //
2360  // Things to do only if modifying density (must come after modifying velocity that enters ucon[TT])
2361  //
2363  PLOOP(pliter,pl){
2364  if(pl==YFL4 || pl==YFL5){
2365  if(startpl<=pl && endpl>=pl){
2366 
2367 
2369 
2370  if(mhdlpflag==UTOPRIMFAILGAMMAPERC || 1){ // GODMARK: always doing it
2371 
2372  if (ucon_calc(&MACP0A1(pv,i,j,k,URAD1-U1), ptrgeom, ucon,others) >= 1) FAILSTATEMENT("fixup.c:utoprimfail_fixup()", "ucon_calc()", 1);
2373 
2374  if(finalstep==1){
2375  // this is not reasonable, because ignores any mass injection required during failure to make sense of solution
2376  FTYPE Unothing[NPR];
2377  UtoU(UEVOLVE,UNOTHING,ptrgeom,MAC(ucons,i,j,k),Unothing);
2378  D0 = Unothing[pl] ;
2379  }
2380  else{
2381  // This is probably not necessary or useful
2382  D0 = MACP0A1(ptoavg,i,j,k,pl)*ucon[TT];
2383  }
2384 
2386  //
2387  // constrain change in density so conserve particle number
2388  //
2390  if(pl==YFL4 || pl==YFL5){
2391  MACP0A1(pv,i,j,k,pl) = D0/ucon[TT];
2392  }
2393  }
2394  }
2395  }
2396  }
2397  }// end over density or scalars
2398 
2399 
2400 
2401 
2402 
2403 #if(0)
2404  // DEBUG problem of launch with pressureless stellar model collapse
2405  PALLLOOP(pl) dualfprintf(fail_file,"nstep=%ld steppart=%d :: i=%d j=%d k=%d pl=%d pv=%21.15g ptoavg=%21.15g\n",nstep,steppart,i,j,k,pl,MACP0A1(pv,i,j,k,pl),MACP0A1(ptoavg,i,j,k,pl));
2406 #endif
2407 
2408 
2409  // int finaluu=0;
2410  // consfixup_1zone(finaluu,i,j,k,ptrgeom, &MACP0A1(pv,i,j,k,0),NULL);
2411 
2412 
2413  } // end if fixedrad==0
2414  }// end if not keeping static
2415  }// end if radiation failed
2416 
2417 
2419  //
2420  // ACCOUNTING (static or average)
2421  //
2423  fixuputoprim_accounting(i, j, k, mhdlpflag, radlpflag, limitgammamhd, limitgammarad, GLOBALPOINT(pflag),pv,ptoavg, ptrgeom, pr0, ucons, finalstep);
2424 
2425 
2426  }// if fixing mhd or fixing radiation
2427 
2428  }// end over COMPZLOOP loop
2429  }// end over parallel region
2430 
2431  return(0);
2432 }
2433 
2434 
2435 
2436 
2437 
2438 
2439 
2440 
2442 int fixup_utoprim_nofixup(int stage, FTYPE (*pv)[NSTORE2][NSTORE3][NPR], FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep)
2443 {
2444  FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR];
2445 
2446  // this average only works if using 4 velocity since only then guaranteed solution is good after interpolation
2447  if(WHICHVEL==VEL3) return(0); // just stick with static, best can do
2448  if(EOMTYPE==EOMFFDE || EOMTYPE==EOMFFDE2) return(0); // nothing to do
2449 
2450 
2452  //
2453  // Just loop over and only report problems
2454  //
2456 
2457  ptoavg=pv;
2458 
2459 
2461 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOM // accounting requires state stuff
2462  {
2463  int i,j,k,pl,pliter;
2464  FTYPE pr0[NPR];
2465  PFTYPE mhdlpflag,radlpflag;
2466  struct of_geom geomdontuse;
2467  struct of_geom *ptrgeom=&geomdontuse;
2468 
2469 
2471 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
2473  OPENMP3DLOOPBLOCK2IJK(i,j,k);
2474 
2475 
2476  // get failure flag
2477  mhdlpflag=GLOBALMACP0A1(pflag,i,j,k,FLAGUTOPRIMFAIL);
2478  radlpflag=GLOBALMACP0A1(pflag,i,j,k,FLAGUTOPRIMRADFAIL);
2479 
2480 
2481  if(IFUTOPRIMFAIL(mhdlpflag)||IFUTOPRIMFAIL(radlpflag)){
2482 
2483  PALLLOOP(pl) pr0[pl]=MACP0A1(ptoavg,i,j,k,pl);
2484  get_geometry(i,j,k,CENT,ptrgeom);
2485 
2487  //
2488  // ACCOUNTING (static or average)
2489  //
2491  fixuputoprim_accounting(i, j, k, mhdlpflag, radlpflag, 0, 0, GLOBALPOINT(pflag),pv,ptoavg, ptrgeom, pr0, ucons, finalstep);
2492 
2493  }// end if failure
2494  }// end over COMPZLOOP loop
2495  }// end over parallel region
2496 
2497  return(0);
2498 }
2499 
2500 
2501 
2502 
2503 
2504 
2505 
2506 
2507 
2509 static int fixup_negdensities(int whicheomset, int *fixed, int startpl, int endpl, int i, int j, int k, PFTYPE lpflag, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom, FTYPE *pr0, FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep)
2510 {
2511  FTYPE prguess[NPR],prceiling[NPR];
2512 
2513 
2514  if(whicheomset==EOMSETMHD){
2516  //
2517  // deal with negative internal energy as special case of failure
2518  //
2519 
2520  if(*fixed!=0){
2521  if(lpflag==UTOPRIMFAILUNEG){
2522 
2523  if(STEPOVERNEGU==NEGDENSITY_NEVERFIXUP){ if(HANDLEUNEG==1) *fixed=1; }
2525 
2526  if(HANDLEUNEG==1){
2527  // set back to floor level
2528  set_density_floors(ptrgeom,MAC(pv,i,j,k),prguess,prceiling);
2529  // GODMARK -- maybe too agressive, maybe allow more negative?
2530 
2532  // then pv is previous timestep value and can use to make fix
2533  if(-MACP0A1(pv,i,j,k,UU)<prguess[UU]){ *fixed=1; MACP0A1(pv,i,j,k,UU)=prguess[UU];} // otherwise assume really so bad that failure
2534  }
2535  else{
2536  // just treat as floor for all failures since do not know what updated quantity is
2537  MACP0A1(pv,i,j,k,UU)=prguess[UU];
2538  *fixed=1;
2539  }
2540  }// end if handling u<zerouuperbaryon*prim[RHO] in special way
2541  }// end if not allowing negative u or if allowing but not yet final step
2542  else if((STEPOVERNEGU==NEGDENSITY_FIXONFULLSTEP)&&(!finalstep)){
2543  if(HANDLEUNEG==1) *fixed=1; // tells rest of routine to leave alone and say ok solution, but don't use it to fix convergence failures for other zones
2544  }
2545  }// end if u<zerouuperbaryon*prim[RHO]
2546  }// end if not fixed
2547 
2548 
2550  //
2551  // deal with negative density as special case of failure (as for internal energy above)
2552  //
2553 
2554  if(*fixed!=0){
2555  if(lpflag==UTOPRIMFAILRHONEG){
2556 
2557  if(STEPOVERNEGRHO==NEGDENSITY_NEVERFIXUP){ if(HANDLERHONEG) *fixed=1; }
2559 
2560  if(HANDLERHONEG==1){
2561  // set back to floor level
2562  set_density_floors(ptrgeom,MAC(pv,i,j,k),prguess,prceiling);
2563  // GODMARK -- maybe too agressive, maybe allow more negative?
2564 
2566  // then pv is previous timestep value and can use to make fix
2567  if(-MACP0A1(pv,i,j,k,RHO)<prguess[RHO]){ *fixed=1; MACP0A1(pv,i,j,k,RHO)=prguess[RHO];} // otherwise assume really so bad that failure
2568  }
2569  else{
2570  // just treat as floor for all failures since do not know what updated quantity is
2571  MACP0A1(pv,i,j,k,RHO)=prguess[RHO];
2572  *fixed=1;
2573  }
2574  }// end if handling rho<0 in special way
2575  }// end if not allowing negative rho or if allowing but not yet final step
2576  else if((STEPOVERNEGRHO==NEGDENSITY_FIXONFULLSTEP)&&(!finalstep)){
2577  if(HANDLERHONEG) *fixed=1; // tells rest of routine to leave alone and say ok solution, but don't use it to fix convergence failures for other zones
2578  }
2579  }// end if rho<0
2580  }// end if not fixed
2581 
2582 
2583 
2585  //
2586  // deal with negative density and negative internal energy as special case of failure (as for internal energy above)
2587  //
2588 
2589  if(*fixed!=0){
2590  if(lpflag==UTOPRIMFAILRHOUNEG){
2591 
2593  // GODMARK: Why use STEPOVERNEGU and STEPOVERNEGRH instead of STEPOVERNEGRHOU below?
2595 
2596  if(HANDLERHOUNEG==1){
2597  // set back to floor level
2598  set_density_floors(ptrgeom,MAC(pv,i,j,k),prguess,prceiling);
2599  // GODMARK -- maybe too agressive, maybe allow more negative?
2600 
2602  // then pv is previous timestep value and can use to make fix
2603  if(-MACP0A1(pv,i,j,k,UU)<prguess[UU]){ *fixed=1; MACP0A1(pv,i,j,k,UU)=prguess[UU];} // otherwise assume really so bad that failure
2604  if(-MACP0A1(pv,i,j,k,RHO)<prguess[RHO]){ *fixed=1; MACP0A1(pv,i,j,k,RHO)=prguess[RHO];} // otherwise assume really so bad that failure
2605  }
2606  else{
2607  // just treat as floor for all failures since do not know what updated quantity is
2608  MACP0A1(pv,i,j,k,UU)=prguess[UU];
2609  MACP0A1(pv,i,j,k,RHO)=prguess[RHO];
2610  *fixed=1;
2611  }
2612  }// end if handling rho<0 and u<zerouuperbaryon*prim[RHO] in special way
2613  }// end if not allowing negative rho or if allowing but not yet final step
2614  else if(STEPOVERNEGRHOU==NEGDENSITY_FIXONFULLSTEP &&(!finalstep)){
2615  if(HANDLERHOUNEG) *fixed=1; // tells rest of routine to leave alone and say ok solution, but don't use it to fix convergence failures for other zones
2616  }
2617  }// end if rho<0 and u<zerouuperbaryon*prim[RHO]
2618  }// end if not fixed
2619  }
2620  else if(whicheomset==EOMSETRAD){
2621 
2623  //
2624  // deal with negative internal energy as special case of failure
2625  //
2626 
2627  if(*fixed!=0){
2628  if(lpflag==UTOPRIMRADFAILERFNEG){
2629 
2630  if(STEPOVERNEGU==NEGDENSITY_NEVERFIXUP){ if(HANDLEUNEG==1) *fixed=1; }
2632 
2633  if(HANDLEUNEG==1){
2634  // set back to floor level
2635  prguess[URAD0]=ERADLIMIT;
2636 
2638  // then pv is previous timestep value and can use to make fix
2639  if(-MACP0A1(pv,i,j,k,URAD0)<prguess[URAD0]){ *fixed=1; MACP0A1(pv,i,j,k,URAD0)=prguess[URAD0];} // otherwise assume really so bad that failure
2640  }
2641  else{
2642  // just treat as floor for all failures since do not know what updated quantity is
2643  MACP0A1(pv,i,j,k,UU)=prguess[URAD0];
2644  *fixed=1;
2645  }
2646  }// end if handling u<zerouuperbaryon*prim[RHO] in special way
2647  }// end if not allowing negative u or if allowing but not yet final step
2648  else if((STEPOVERNEGU==NEGDENSITY_FIXONFULLSTEP)&&(!finalstep)){
2649  if(HANDLEUNEG==1) *fixed=1; // tells rest of routine to leave alone and say ok solution, but don't use it to fix convergence failures for other zones
2650  }
2651  }// end if u<zerouuperbaryon*prim[RHO]
2652  }// end if not fixed
2653 
2654 
2655  }
2656 
2657 
2658 
2659  return(0);
2660 }
2661 
2662 
2663 
2664 
2665 // DOCOUNTNEG???? only applies for STEPOVERNEG???==NEGDENSITY_NEVERFIXUP
2666 
2667 // whether to count any substep u<zerouuperbaryon*prim[RHO] as failure in debug data
2668 // 2: always counted
2669 // 1: only counted on final substep
2670 // 0: never counted
2671 #define DOCOUNTNEGU 1
2672 
2673 // whether to count any substep rho<0 as failure in debug data
2674 #define DOCOUNTNEGRHO 1
2675 
2676 // whether to count any substep rho<0 && u<zerouuperbaryon*prim[RHO] case as failure in debug data
2677 #define DOCOUNTNEGRHOU 1
2678 
2679 
2680 // whether to make conserved quantity consistent with the associated fixed primitive quantity.
2681 // required at least at the finalstep.
2682 // 0: don't do it
2683 // 1: adjust only if finalstep==1
2684 // 2: adjust for all substeps
2685 #define ADJUSTCONSERVEDQUANTITY 0
2686 
2688 static int fixuputoprim_accounting(int i, int j, int k, PFTYPE mhdlpflag, PFTYPE radlpflag, int limitgammamhd, int limitgammarad, PFTYPE (*lpflag)[NSTORE2][NSTORE3][NUMPFLAGS],FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom, FTYPE *pr0, FTYPE (*uconsinput)[NSTORE2][NSTORE3][NPR], int finalstep)
2689 {
2690  PFTYPE mhdutoprimfailtype,radutoprimfailtype;
2691  int doadjustcons;
2692  struct of_state q;
2693  FTYPE (*utoinvert)[NSTORE2][NSTORE3][NPR];
2694  int docorrectucons;
2695  int pliter,pl;
2696 
2697 
2698 
2699  // store ucons and only change if needed (and handle avoidance of B1,B2,B3 in case ucons points to unewglobal staggered field, while here we operate on centers)
2700  FTYPE ucons[NPR];
2701  if(uconsinput!=NULL){
2702  PLOOP(pliter,pl) ucons[pl]=MACP0A1(uconsinput,i,j,k,pl);
2703  }
2704 
2706  //
2707  // MHD
2708  //
2710 
2711  // account for changes by tracking conserved quantities
2712  // note that if new utoprim solution was impossible, we are using here prior solution as new state, which means the diagnostics won't be acccurate. There's no way to fix this unless the fluxes always give a well-defined new primitive variable.
2713  // specific value of the mhdlpflag>0 communicates the type of failure
2714  if(IFUTOPRIMNOFAIL(mhdlpflag)){
2715  mhdutoprimfailtype=-1;
2716  docorrectucons=0;
2717  }
2718  else if(
2719  (mhdlpflag==UTOPRIMFAILCONV)|| // only used by 5D method currently
2720  (mhdlpflag==UTOPRIMFAILCONVGUESSUTSQ)|| // rest are only used by 1D/2D method currently
2721  (mhdlpflag>=UTOPRIMFAILCONVRET)||
2722  (mhdlpflag==UTOPRIMFAILCONVW)||
2723  (mhdlpflag==UTOPRIMFAILCONVUTSQVERYBAD)||
2724  (mhdlpflag==UTOPRIMFAILNANGUESS)||
2725  (mhdlpflag==UTOPRIMFAILNANRESULT)||
2726  (mhdlpflag==UTOPRIMFAILCONVBADINVERTCOMPARE)||
2727  (mhdlpflag==UTOPRIMFAILCONVUTSQ)||
2728  (mhdlpflag==UTOPRIMFAILFAKEVALUE) // fake value for avoiding MPI boundary call and so MPI boundary values for fixup
2729  ){
2730  mhdutoprimfailtype=COUNTUTOPRIMFAILCONV;
2731  docorrectucons=1;
2732  }
2733  else if(mhdlpflag==UTOPRIMFAILRHONEG){
2734  // whether to count uneg as failure in diagnostic reporting or not
2735  // should really have a new diagnostic for substep u<zerouuperbaryon*prim[RHO] 's.
2737  if(DOCOUNTNEGRHO==1){
2738  if(finalstep){
2739  mhdutoprimfailtype=COUNTUTOPRIMFAILRHONEG;
2740  docorrectucons=1;
2741  }
2742  else{
2743  mhdutoprimfailtype=-1;
2744  docorrectucons=0;
2745  }
2746  }
2747  else if(DOCOUNTNEGRHO==2){
2748  mhdutoprimfailtype=COUNTUTOPRIMFAILRHONEG;
2749  docorrectucons=1;
2750  }
2751  else{
2752  mhdutoprimfailtype=-1;
2753  docorrectucons=0;
2754  }
2755  }
2756  else if((STEPOVERNEGRHO)&&(!finalstep)){
2757  mhdutoprimfailtype=-1;
2758  docorrectucons=0;
2759  }
2760  else{
2761  mhdutoprimfailtype=COUNTUTOPRIMFAILRHONEG;
2762  docorrectucons=1;
2763  }
2764  }
2765  else if(mhdlpflag==UTOPRIMFAILUNEG || mhdlpflag==UTOPRIMFAILU2AVG1|| mhdlpflag==UTOPRIMFAILU2AVG2 || mhdlpflag==UTOPRIMFAILU2AVG1FROMCOLD|| mhdlpflag==UTOPRIMFAILU2AVG2FROMCOLD || mhdlpflag==UTOPRIMFAILURHO2AVG1FROMFFDE){ // GODMARK: maybe want separate accounting
2766  // whether to count uneg as failure in diagnostic reporting or not
2767  // should really have a new diagnostic for substep u<zerouuperbaryon*prim[RHO] 's.
2768 
2769  // default counting:
2770  if(mhdlpflag==UTOPRIMFAILU2AVG1FROMCOLD|| mhdlpflag==UTOPRIMFAILU2AVG2FROMCOLD) mhdutoprimfailtype=COUNTCOLD;
2771  else mhdutoprimfailtype=COUNTUTOPRIMFAILUNEG;
2772 
2773  // default counting:
2774  if(mhdlpflag==UTOPRIMFAILURHO2AVG1FROMFFDE) mhdutoprimfailtype=COUNTFFDE;
2775  else mhdutoprimfailtype=COUNTUTOPRIMFAILUNEG;
2776 
2777  // now set whether to ucons correction or override counting
2779  if(DOCOUNTNEGU==1){
2780  if(finalstep){
2781  docorrectucons=1;
2782  }
2783  else{
2784  mhdutoprimfailtype=-1;
2785  docorrectucons=0;
2786  }
2787  }
2788  else if(DOCOUNTNEGU==2){
2789  docorrectucons=1;
2790  }
2791  else{
2792  mhdutoprimfailtype=-1;
2793  docorrectucons=0;
2794  }
2795  }
2796  else if((STEPOVERNEGU)&&(!finalstep)){
2797  mhdutoprimfailtype=-1;
2798  docorrectucons=0;
2799  }
2800  else{
2801  docorrectucons=1;
2802  }
2803  }
2804  else if(mhdlpflag==UTOPRIMFAILRHOUNEG){
2805  // whether to count uneg as failure in diagnostic reporting or not
2806  // should really have a new diagnostic for substep u<zerouuperbaryon*prim[RHO] 's.
2808  if(DOCOUNTNEGRHOU==1){
2809  if(finalstep){
2810  mhdutoprimfailtype=COUNTUTOPRIMFAILRHOUNEG;
2811  docorrectucons=1;
2812  }
2813  else{
2814  mhdutoprimfailtype=-1;
2815  docorrectucons=0;
2816  }
2817  }
2818  else if(DOCOUNTNEGRHOU==2){
2819  mhdutoprimfailtype=COUNTUTOPRIMFAILRHOUNEG;
2820  docorrectucons=1;
2821  }
2822  else{
2823  mhdutoprimfailtype=-1;
2824  docorrectucons=0;
2825  }
2826  }
2827  else if((STEPOVERNEGRHOU)&&(!finalstep)){
2828  mhdutoprimfailtype=-1;
2829  docorrectucons=0;
2830  }
2831  else{
2832  mhdutoprimfailtype=COUNTUTOPRIMFAILRHOUNEG;
2833  docorrectucons=1;
2834  }
2835  }
2836  else if(mhdlpflag==UTOPRIMFAILGAMMAPERC){
2837  mhdutoprimfailtype=COUNTGAMMAPERC;
2838  docorrectucons=1;
2839  }
2840  else if(mhdlpflag==UTOPRIMFAILUPERC){
2841  mhdutoprimfailtype=COUNTUPERC;
2842  docorrectucons=1;
2843  }
2844  else if(mhdlpflag==UTOPRIMFAILFIXEDENTROPY){
2845  mhdutoprimfailtype=COUNTENTROPY;
2846  docorrectucons=0; // account, but don't change conserved quantities
2847  }
2848  else if(mhdlpflag==UTOPRIMFAILFIXEDCOLD){
2849  mhdutoprimfailtype=COUNTCOLD;
2850  docorrectucons=0; // account, but don't change conserved quantities
2851  }
2852  else if(mhdlpflag==UTOPRIMFAILFIXEDBOUND1){
2853  mhdutoprimfailtype=COUNTBOUND1;
2854  docorrectucons=0; // account, but don't change conserved quantities
2855  }
2856  else if(mhdlpflag==UTOPRIMFAILFIXEDBOUND2){
2857  mhdutoprimfailtype=COUNTBOUND2;
2858  docorrectucons=0; // account, but don't change conserved quantities
2859  }
2860  else if(mhdlpflag==UTOPRIMFAILFIXEDUTOPRIM){
2861  dualfprintf(fail_file,"prior pflag not cleared: nstep=%ld steppart=%d t=%21.15g i=%d j=%d k=%d \n",nstep,steppart,t,i,j,k);
2862  mhdutoprimfailtype=-1;
2863  docorrectucons=0;
2864  }
2865  else{
2866  dualfprintf(fail_file,"No such pflag failure type: %d for t=%21.15g nstep=%ld steppart=%d i=%d j=%d k=%d\n",mhdlpflag,t,nstep,steppart,i,j,k);
2867  myexit(1);
2868  }
2869 
2870 
2872  //
2873  // RADIATION
2874  //
2876 
2877  if(IFUTOPRIMNOFAIL(radlpflag)){
2878  radutoprimfailtype=-1;
2879  docorrectucons=0;
2880  }
2881  else if(radlpflag>=UTOPRIMRADFAILCASE1A || radlpflag<=UTOPRIMRADFAILCASE3B || radlpflag==UTOPRIMRADFAILERFNEG){
2882  radutoprimfailtype=COUNTRADLOCAL;
2883  docorrectucons=1;
2884  }
2885  else if(radlpflag>=UTOPRIMRADFAILBAD1 || radlpflag==UTOPRIMRADFAILGAMMAHIGH || radlpflag==UTOPRIMRADFAILERFNEG){
2886  radutoprimfailtype=COUNTRADNONLOCAL;
2887  docorrectucons=1;
2888  }
2889  else if(radlpflag==UTOPRIMRADFAILFIXEDUTOPRIMRAD){
2890  dualfprintf(fail_file,"prior rad pflag not cleared: nstep=%ld steppart=%d t=%21.15g i=%d j=%d k=%d \n",nstep,steppart,t,i,j,k);
2891  radutoprimfailtype=-1;
2892  docorrectucons=0;
2893  }
2894 
2895 
2896 
2898  //
2899  // Check if either MHD or RADIATION was corrected
2900  //
2902 
2903  if(mhdutoprimfailtype!=-1 || radutoprimfailtype!=-1 || limitgammamhd==-1 || limitgammarad==-1){
2904  if(docorrectucons==1){
2905  docorrectucons=(DOENOFLUX != NOENOFLUX);
2906  }
2907 
2909  //
2910  // reset true pflag counter to "no" (fixed) failure so diagnostics account for change
2911  //
2913  MACP0A1(lpflag,i,j,k,FLAGUTOPRIMFAIL)=UTOPRIMFAILFIXEDUTOPRIM;
2914  MACP0A1(lpflag,i,j,k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILFIXEDUTOPRIMRAD;
2915 
2916 
2917 
2918  // diagnostics
2919  // FTYPE prdiag[NPR],pr[NPR];
2920  // PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
2921  // int doingmhdfixup=(mhdutoprimfailtype!=-1); // diag_fixup() accounting diagnostics part doesn't have radiation yet
2922 
2923  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2924  // dualfprintf(fail_file,"BEFORE IN FIXUPUTOPRIM: finalstep=%d\n",finalstep);
2925  // }
2926 
2927 
2928  // diag_fixup(docorrectucons,prdiag, MAC(pv,i,j,k), ucons, ptrgeom, finalstep, doingmhdfixup, (int)mhdutoprimfailtype); // do corrections in general, but only include accounting for MHD case so far (KORALTODO, not too crucial, just diags).
2929  // PLOOP(pliter,pl) prdiag[pl]=MACP0A1(pv,i,j,k,pl);
2930 
2931  // pr0=prdiag only correct as reference primitive if was no failure of any kind, but some kind of failure if here, so need to use ucons as reference to what should be.
2932  FTYPE Uievolve[NPR];
2933  PLOOP(pliter,pl) Uievolve[pl] = MACP0A1(uconsinput,i,j,k,pl);
2934  diag_fixup_Ui_pf(docorrectucons, Uievolve, MAC(pv,i,j,k), ptrgeom, finalstep,(int)mhdutoprimfailtype, NULL);
2935 
2936 
2937 
2938 
2939 
2940  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2941  // dualfprintf(fail_file,"AFTER IN FIXUPUTOPRIM: UievolveRHO=%21.15g\n",Uievolve[RHO]*dx[1]*dx[2]*dx[3]);
2942  // }
2943 
2944 
2945  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
2946  // struct of_state qb;
2947  // get_state(MAC(pv,i,j,k),ptrgeom,&qb);
2948  // FTYPE ub[NPR],ubabs[NPR];
2949  // int uutype=UDIAG;
2950  // primtoU(uutype,MAC(pv,i,j,k),&qb,ptrgeom,ub,ubabs);
2951  // dualfprintf(fail_file,"URHOINFIXUPUTOPRIMACCTT=%21.15g\n",ub[RHO]*dx[1]*dx[2]*dx[3]);
2952  // }
2953 
2954 
2955 
2956  // now adjust uf or ucum so agrees [already done in diag_fixup() but only if final step. This allows one to do it on any step in case want to control behavior of conserved quantities or primitive quantities used to create fluxes.
2957  if(ADJUSTCONSERVEDQUANTITY&&docorrectucons){
2958 
2959  if((ADJUSTCONSERVEDQUANTITY==1)&&(finalstep)) doadjustcons=1;
2960  else if(ADJUSTCONSERVEDQUANTITY==2) doadjustcons=1;
2961  else doadjustcons=0;
2962 
2963  if(doadjustcons){
2964  //utoinvert=ucons;
2965  // if(finalstep){ // last call, so ucum is cooked and ready to eat!
2966  // }
2967  // else{ // otherwise still iterating on primitives
2968  // utoinvert=ulast;
2969  // }
2970 
2971  MYFUN(get_state(MAC(pv,i,j,k), ptrgeom, &q),"fixup.c:fixup_utoprim()", "get_state()", 1);
2972  MYFUN(primtoU(UEVOLVE,MAC(pv,i,j,k), &q, ptrgeom, ucons, NULL),"fixup.c:fixup_utoprim()", "primtoU()", 1);
2973  }
2974  }
2975 
2976  // copy over ucons result in case changed.
2977  if(uconsinput!=NULL && docorrectucons){
2978  PLOOP(pliter,pl){
2979  // if staggered field, avoid modifying field since at FACEs, not CENT where pr lives.
2980  if(BPL(pl)==0 && FLUXB==FLUXCTSTAG || FLUXB==FLUXCTTOTH){
2981  MACP0A1(uconsinput,i,j,k,pl) = ucons[pl];
2982  }
2983  }
2984  }
2985 
2986  }// end if mhdutoprimfailtype!=-1 || radutoprimfailtype!=-1
2987 
2988 
2989 
2990 #if(DOSUPERDEBUG)
2991  // only used to keep track of normal non-failure points
2992  // some non-utoprim-failure points will be picked up by this. I.E. those with limitgammaact/flooract/inflowact
2993  if(mhdutoprimfailtype==-1) superdebug_utoprim(pr0,MAC(pv,i,j,k),ptrgeom,mhdutoprimfailtype);
2994  // collect values for non-failed and failed zones
2995 #endif
2996 
2997 
2998  return(0);
2999 }
3000 
3001 
3002 // what quantities to average or treat in fixup_utoprim()
3003 // only touch mhd quantities for mhd case, rad quantities for rad case, and never touch field
3004 #define PLOOPSTARTEND(pl) for(pl=startpl;pl<=endpl;pl++) if((NONRADFULLPL(pl) && doingmhd || RADFULLPL(pl) && doingmhd==0) && BPL(pl)==0)
3005 
3006 
3007 
3008 
3009 // sums need to be symmerized in order to preserve exact symmetry
3010 #define AVG4_1(pr,i,j,k,pl) (0.25*((MACP0A1(pr,i,jp1mac(j),k,pl)+MACP0A1(pr,i,jm1mac(j),k,pl))+(MACP0A1(pr,im1mac(i),j,k,pl)+MACP0A1(pr,ip1mac(i),j,k,pl)))) // symmetrized sum
3011 #define AVG4_2(pr,i,j,k,pl) (0.25*((MACP0A1(pr,ip1mac(i),jp1mac(j),k,pl)+MACP0A1(pr,ip1mac(i),jm1mac(j),k,pl))+(MACP0A1(pr,im1mac(i),jp1mac(j),k,pl)+MACP0A1(pr,im1mac(i),jm1mac(j),k,pl)))) //symmetrized sum
3012 
3013 #define AVG2_1(pr,i,j,k,pl) (0.5*(MACP0A1(pr,i,jp1mac(j),k,pl)+MACP0A1(pr,i,jm1mac(j),k,pl)))
3014 #define AVG2_2(pr,i,j,k,pl) (0.5*(MACP0A1(pr,ip1mac(i),j,k,pl)+MACP0A1(pr,im1mac(i),j,k,pl)))
3015 #define AVG2_3(pr,i,j,k,pl) (0.5*(MACP0A1(pr,ip1mac(i),jp1mac(j),k,pl)+MACP0A1(pr,im1mac(i),jm1mac(j),k,pl)))
3016 #define AVG2_4(pr,i,j,k,pl) (0.5*(MACP0A1(pr,ip1mac(i),jm1mac(j),k,pl)+MACP0A1(pr,im1mac(i),jp1mac(j),k,pl)))
3017 
3018 #define AVG4_1(pr,i,j,k,pl) (0.25*((MACP0A1(pr,i,jp1mac(j),k,pl)+MACP0A1(pr,i,jm1mac(j),k,pl))+(MACP0A1(pr,im1mac(i),j,k,pl)+MACP0A1(pr,ip1mac(i),j,k,pl)))) // symmetrized sum
3019 #define AVG4_2(pr,i,j,k,pl) (0.25*((MACP0A1(pr,ip1mac(i),jp1mac(j),k,pl)+MACP0A1(pr,ip1mac(i),jm1mac(j),k,pl))+(MACP0A1(pr,im1mac(i),jp1mac(j),k,pl)+MACP0A1(pr,im1mac(i),jm1mac(j),k,pl)))) //symmetrized sum
3020 
3021 
3022 // whether doing causal averaging for non-U2AVG failures
3023 #define CAUSALAVG 0
3024 
3025 #define CAUSALAVG_WHEN_U2AVG 0 // causal way -- uses same normal loops
3026 #define SIMPLEAVG_WHEN_U2AVG 1 // normal average
3027 #define MAXUPOSAVG_WHEN_U2AVG 2 // Sasha way -- take min of positive internal energies
3028 #define CAUSAL_THENMIN_WHEN_U2AVG 3 // Jon way -- use min of ANY (pos or neg) answer between (1) causal and (2) min of all positive
3029 
3030 //#define HOWTOAVG_WHEN_U2AVG SIMPLEAVG_WHEN_U2AVG // can artificially pump up internal energy as in caustic test
3031 //#define HOWTOAVG_WHEN_U2AVG CAUSALAVG_WHEN_U2AVG
3032 #define HOWTOAVG_WHEN_U2AVG MAXUPOSAVG_WHEN_U2AVG
3033 //#define HOWTOAVG_WHEN_U2AVG CAUSAL_THENMIN_WHEN_U2AVG
3034 
3036 static int general_average(int useonlynonfailed, int numbndtotry, int maxnumbndtotry, int startpl, int endpl, int i, int j, int k, int doingmhd, PFTYPE mhdlpflag, PFTYPE radlpflag, PFTYPE (*lpflagfailorig)[NSTORE2][NSTORE3][NUMFAILPFLAGS],FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom)
3037 {
3038  int doavgcausal,failavglooptype;
3039  int pl,pliter;
3040  int ii,jj,kk;
3041  int jjj;
3042  struct of_state state_pv;
3043  FTYPE cminmax[NDIM][NUMCS];
3044  FTYPE superfast[NDIM];
3045  int numavg[NPR];
3046  int numavg0,numavg1[NPR];
3047  FTYPE mysum[2][NPR];
3048  int numupairs,qq,thisnotfail,thatnotfail,rnx,rny,rnz;
3049  FTYPE ref[NPR];
3050  FTYPE ftemp,ftemp1,ftemp2;
3051  FTYPE lastmin[NPR],avganswer0[NPR],avganswer1[NPR];
3052  int ignorecourant=0;
3053  int factor;
3054  PFTYPE lpflag;
3055  int whichpflag;
3056 
3057 
3058  prod0dualfprintf(debugfail>=2,fail_file,"uc2generalA: doingmhd=%d mhdlpflag=%d radlpflag=%d startpl=%d endpl=%d :: i=%d j=%d k=%d\n",doingmhd,mhdlpflag,radlpflag,startpl,endpl,i,j,k); // not too much
3059  // if(debugfail>=2) for(pl=startpl; pl<=endpl; pl++) dualfprintf(fail_file,"uc2generalSTART: pl=%d pv=%g\n",pl,MACP0A1(pv,i,j,k,pl));
3060 
3061 
3062  if(doingmhd==1){ // if MHD
3063  whichpflag=FLAGUTOPRIMFAIL;
3064  lpflag=mhdlpflag;
3065 
3066  if(mhdlpflag==UTOPRIMFAILU2AVG1 || mhdlpflag==UTOPRIMFAILU2AVG2 || mhdlpflag==UTOPRIMFAILU2AVG1FROMCOLD || mhdlpflag==UTOPRIMFAILU2AVG2FROMCOLD){
3067  if(HOWTOAVG_WHEN_U2AVG==CAUSALAVG_WHEN_U2AVG){ // causal type
3068  doavgcausal=1;
3069  failavglooptype=0;
3070  }
3071  else if(HOWTOAVG_WHEN_U2AVG==MAXUPOSAVG_WHEN_U2AVG){ // Sasha type
3072  doavgcausal=0; // doesn't hurt, it's just wasted process
3073  failavglooptype=1;
3074  }
3075  else if(HOWTOAVG_WHEN_U2AVG==SIMPLEAVG_WHEN_U2AVG){ // simple type
3076  doavgcausal=0;
3077  failavglooptype=0;
3078  }
3079  else if(HOWTOAVG_WHEN_U2AVG==CAUSAL_THENMIN_WHEN_U2AVG){ // Jon's mixed type
3080  doavgcausal=1;
3081  failavglooptype=2; // do both loops
3082  }
3083  }
3084  else if(CAUSALAVG){ // other types of failures besides U2AVG
3085  failavglooptype=0;
3086  doavgcausal=1;
3087  }
3088  else{
3089  doavgcausal=0;
3090  failavglooptype=0; // must stay 0 since can't assume a density of some kind with min value
3091  }
3092  }
3093  else{ // if RAD
3094  whichpflag=FLAGUTOPRIMRADFAIL;
3095  lpflag=radlpflag;
3096  doavgcausal=0;
3097  failavglooptype=0; // must stay 0
3098  }
3099 
3100 
3101 
3102 
3103 
3104  if(doavgcausal){
3106  // first get wave speed to check if superfast so need causal averaging
3107  MYFUN(get_state(MAC(ptoavg,i,j,k), ptrgeom, &state_pv),"fixup.c:fixup_utporim()", "get_state()", 1);
3108  if(N1NOT1){
3109  MYFUN(vchar_all(MAC(ptoavg,i,j,k), &state_pv, 1, ptrgeom, &cminmax[1][CMAX], &cminmax[1][CMIN],&ignorecourant),"fixup.c:fixup_utoprim()", "vchar_all() dir=1or2", 1);
3110  }
3111  if(N2NOT1){
3112  MYFUN(vchar_all(MAC(ptoavg,i,j,k), &state_pv, 2, ptrgeom, &cminmax[2][CMAX], &cminmax[2][CMIN],&ignorecourant),"fixup.c:fixup_utoprim()", "vchar_all() dir=1or2", 2);
3113  }
3114  if(N3NOT1){
3115  MYFUN(vchar_all(MAC(ptoavg,i,j,k), &state_pv, 3, ptrgeom, &cminmax[3][CMAX], &cminmax[3][CMIN],&ignorecourant),"fixup.c:fixup_utoprim()", "vchar_all() dir=1or2", 3);
3116  }
3117  SLOOPA(jjj){
3118  superfast[jjj]=0; // assume subfast
3119 
3120 #if(1)
3121  if(cminmax[jjj][CMIN]>0.0){ superfast[jjj]=1.0;} // superfast to right
3122  else if(cminmax[jjj][CMAX]<0.0){ superfast[jjj]=-1.0;} // superfast to left
3123 #else
3124  if(MACP0A1(ptoavg,i,j,k,U1-1+jjj)>0.0){ superfast[jjj]=1.0;} // wind blows to right
3125  else if(MACP0A1(ptoavg,i,j,k,U1-1+jjj)<0.0){ superfast[jjj]=-1.0;} // wind blows to left
3126 #endif
3127  }
3128 
3129  } // end if doing causal loop -- end getting wave speeds
3130 
3131 
3132 
3133 
3134 
3135 
3137  //
3138  // average all surrounding good values (keeps symmetry)
3139  //
3141  numavg0=0;
3142  PLOOPSTARTEND(pl){
3143  numavg1[pl]=0;
3144  numavg[pl]=0;
3145  mysum[0][pl]=0.0;
3146  mysum[1][pl]=0.0;
3147  lastmin[pl]=VERYBIG;
3148  }
3149  // size of little averaging box, from -NUMPFLAGBNDx to +NUMPFLAGBNDx
3150  int rbndx=MIN(numbndtotry,NUMPFLAGBND1);
3151  int rbndy=MIN(numbndtotry,NUMPFLAGBND2);
3152  int rbndz=MIN(numbndtotry,NUMPFLAGBND3);
3153  rnx=(SHIFT1==1) ? (rbndx*2+1) : 1;
3154  rny=(SHIFT2==1) ? (rbndy*2+1) : 1;
3155  rnz=(SHIFT3==1) ? (rbndz*2+1) : 1;
3156 
3157  // number of unique pairs ( NUMPFLAGBND1*NUMPFLAGBND2*NUMPFLAGBND3 + NUMPFLAGBND1
3158  numupairs=(int)(rnx*rny*rnz-1)/2;
3159 
3160  for(qq=0;qq<numupairs;qq++){
3161 
3162  // 1-d to 3D index
3163  ii=(int)(qq%rnx)-rbndx;
3164  jj=(int)((qq%(rnx*rny))/rnx)-rbndy;
3165  kk=(int)(qq/(rnx*rny))-rbndz;
3166 
3167  if(useonlynonfailed==1){
3168  if(doingmhd){
3169  thisnotfail=IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i+ii,j+jj,k+kk,whichpflag));
3170  thatnotfail=IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i-ii,j-jj,k-kk,whichpflag));
3171  }
3172  else{
3173  thisnotfail=IFUTOPRIMRADNOFAILORFIXED(MACP0A1(lpflagfailorig,i+ii,j+jj,k+kk,whichpflag));
3174  thatnotfail=IFUTOPRIMRADNOFAILORFIXED(MACP0A1(lpflagfailorig,i-ii,j-jj,k-kk,whichpflag));
3175  }
3176  }
3177  else{
3178  // here lpflagfailorig can be just NULL since not used
3179  thisnotfail=thatnotfail=1; // just ignores whether failed
3180  }
3181 
3182 
3183 
3184 
3185  if(doavgcausal){
3186 #if(1)
3187  if( ii<0 && superfast[1]>0 && thisnotfail ) thatnotfail=0; // then don't need this one
3188  if( ii>0 && superfast[1]<0 && thatnotfail ) thisnotfail=0; // then don't need this one
3189  if( jj<0 && superfast[2]>0 && thisnotfail ) thatnotfail=0; // then don't need this one
3190  if( jj>0 && superfast[2]<0 && thatnotfail ) thisnotfail=0; // then don't need this one
3191  if( kk<0 && superfast[3]>0 && thisnotfail ) thatnotfail=0; // then don't need this one
3192  if( kk>0 && superfast[3]<0 && thatnotfail ) thisnotfail=0; // then don't need this one
3193 #elif(0)
3194  if(i<totalsize[1]/2 && ii<0) thatnotfail=0;
3195  if(i<totalsize[1]/2 && ii>0) thisnotfail=0;
3196  if(i>=totalsize[1]/2 && ii<0) thisnotfail=0;
3197  if(i>=totalsize[1]/2 && ii>0) thatnotfail=0;
3198 #endif
3199 
3200  }
3201 
3202 #if(1)
3203  // bigger than myself and absolute limit
3204  PLOOPSTARTEND(pl){
3205  ref[pl]=0.0; // default
3206  if(pl==RHO) ref[pl]=MAX(1.001*RHOMINLIMIT,MACP0A1(ptoavg,i,j,k,pl)); // MHD
3207  else if(pl==UU) ref[pl]=MAX(1.001*UUMINLIMIT,MACP0A1(ptoavg,i,j,k,pl)); // MHD
3208  else if(pl==URAD0) ref[pl]=MAX(1.001*ERADLIMIT,MACP0A1(ptoavg,i,j,k,URAD0)); // RAD
3209  }
3210 #elif(0)
3211  // bigger than 0
3212  PLOOPSTARTEND(pl) ref[pl]=0.0;
3213 #endif
3214 
3215  // if(failavglooptype==1 || failavglooptype==2){ // only use if positive
3216 
3217  // number of quantities one summed
3218  numavg0+=thisnotfail+thatnotfail;
3219 
3220  // do sum or min of these 2 pairs
3221  PLOOPSTARTEND(pl){
3222  ftemp1=MACP0A1(ptoavg,i+ii,j+jj,k+kk,pl);
3223  ftemp2=MACP0A1(ptoavg,i-ii,j-jj,k-kk,pl);
3224 
3226  // AVG type
3228  mysum[qq%2][pl]+=ftemp1*thisnotfail + ftemp2*thatnotfail;
3229 
3231  // MIN type
3233 #if(0)
3234  if(ftemp1>ref[pl] && thisnotfail){
3235  lastmin[pl]=MIN(lastmin[pl],ftemp1); // smallest positive number
3236  numavg1[pl]++;
3237  }
3238 
3239  if(ftemp2>ref[pl] && thatnotfail){
3240  lastmin[pl]=MIN(lastmin[pl],ftemp2);
3241  numavg1[pl]++;
3242  }
3243 #else
3244  // if(pl==8) dualfprintf(fail_file,"ii=%d jj=%d kk=%d i+ii=%d j+jj=%d k+kk=%d pl=%d testing: %g>%g && %g>%g : %d %d\n",ii,jj,kk,i+ii,j+jj,k+kk,pl,ftemp1,ref[pl],ftemp2,ref[pl],thisnotfail,thatnotfail);
3245  if(ftemp1>ref[pl] && thisnotfail && ftemp2>ref[pl] && thatnotfail){
3246  lastmin[pl]=MIN(MIN(lastmin[pl],ftemp1),ftemp2); // smallest positive number if both of pair are larger than my value (else keep my small value)
3247  numavg1[pl]+=2;
3248  }
3249  else if(ftemp1>ref[pl] && thisnotfail){
3250  lastmin[pl]=MIN(lastmin[pl],ftemp1); // smallest positive number if both of pair are larger than my value (else keep my small value)
3251  numavg1[pl]++;
3252  }
3253  else if(ftemp2>ref[pl] && thatnotfail){
3254  lastmin[pl]=MIN(lastmin[pl],ftemp2); // smallest positive number if both of pair are larger than my value (else keep my small value)
3255  numavg1[pl]++;
3256  }
3257 #endif
3258  }// pl loop
3259  } //end loop over pairs
3260 
3261 
3262 
3263 
3264 
3266  //
3267  // all loops over surrounding points is done, now get average answer
3268  //
3271  // NORMAL:
3273  if(numavg0!=0){
3274  PLOOPSTARTEND(pl){
3275  avganswer0[pl]=(mysum[0][pl]+mysum[1][pl])/((FTYPE)(numavg0));
3276  }
3277  }
3278  PLOOPSTARTEND(pl){
3279  avganswer1[pl]=lastmin[pl];
3280  }
3281 
3282 
3283 
3285  //
3286  // choose final answer (avg or min)
3287  //
3289 
3290  int doingavgtype[NPR];
3291  PLOOPSTARTEND(pl){
3292  doingavgtype[pl]=-1; // default avoidance of pl
3293 
3294  // default
3295  if(failavglooptype==0 || ((failavglooptype==2)&&(numavg1[pl]==0)) ){
3296  doingavgtype[pl]=1;
3297  }
3298  if(failavglooptype==1 || ((failavglooptype==2)&&(numavg0==0)) ){
3299  doingavgtype[pl]=0;
3300  }
3301 
3302 
3303  // override
3304  if(doingmhd==0 && radlpflag==UTOPRIMRADFAILERFNEG && pl==URAD0 || doingmhd==1 && lpflag==UTOPRIMFAILRHONEG && pl==RHO || doingmhd==1 && lpflag==UTOPRIMFAILUNEG && pl==UU || doingmhd==1 && lpflag==UTOPRIMFAILRHOUNEG && (pl==RHO || pl==UU)){
3305  doingavgtype[pl]=0; // min type
3306  }
3307  else doingavgtype[pl]=1; // avg type
3308  }
3309 
3310 
3311 
3312  int numavgfinal=256; // just large number (at least (2*NxBND)**3
3313  PLOOPSTARTEND(pl){// should only be over specific density(s)
3314  // choose min
3315  if(numavg1[pl]!=0 && doingavgtype[pl]==0){
3316  MACP0A1(pv,i,j,k,pl)=avganswer1[pl]; // else keep same as original answer
3317  // dualfprintf(fail_file,"HERE: pl=%d %21.15g %d\n",pl,MACP0A1(pv,i,j,k,pl),numavg1[pl]);
3318  numavg[pl]=numavg1[pl];
3319  }
3320  // choose avg
3321  if(numavg0!=0 && doingavgtype[pl]==1){
3322  MACP0A1(pv,i,j,k,pl)=avganswer0[pl];
3323  numavg[pl]=numavg0;
3324  }
3325  numavgfinal=MIN(numavg[pl],numavgfinal); // get minimum number of good points over those wanted "average". If one was bad, have to do nogood version
3326  }// end pl loop
3327 
3328 
3329 
3330  if( lpflag==UTOPRIMFAILU2AVG2){ // lpflag here is either for MHD or RAD depending upon doingmhd=1 or 0
3331  if(numbndtotry==maxnumbndtotry) numavgfinal++; // assume at least always one good one so don't treat as real failure if no good values surrounding. But only do so if last chance for no good average.
3332  }
3333  // else use real numavgfinal
3334 
3335 
3336  if(numavgfinal==0){
3337  return(1);
3338  }
3339 
3340  // good value exist
3341  return(0);
3342 }
3343 
3344 
3345 
3346 
3348 static int simple_average(int startpl, int endpl, int i, int j, int k,int doingmhd, PFTYPE (*lpflagfailorig)[NSTORE2][NSTORE3][NUMFAILPFLAGS],FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR])
3349 {
3350  int pl,pliter;
3351  int whichpflag;
3352 
3353  prod0dualfprintf(debugfail>=2,fail_file,"uc2simple: i=%d j=%d k=%d\n",i,j,k); // not too much
3354 
3355 
3356 
3357  if(doingmhd==1){ // if MHD
3358  whichpflag=FLAGUTOPRIMFAIL;
3359  }
3360  else{ // if RAD
3361  whichpflag=FLAGUTOPRIMRADFAIL;
3362  }
3363 
3364 
3366  //
3367  // 4 VALUES
3368  //
3370  if( // but if surrounded by good values
3371  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i,jp1mac(j),k,whichpflag)))&&
3372  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i,jm1mac(j),k,whichpflag)))&&
3373  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),j,k,whichpflag)))&&
3374  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),j,k,whichpflag)))
3375  ){
3376  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected1\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3377  // then average
3378  // don't mess with B field, it's correct already
3379  PLOOPSTARTEND(pl){
3380  MACP0A1(pv,i,j,k,pl)=AVG4_1(ptoavg,i,j,k,pl);
3381  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3382  }
3383  }
3384  else if( // but if surrounded by good values
3385  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),jp1mac(j),k,whichpflag)))&&
3386  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),jm1mac(j),k,whichpflag)))&&
3387  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),jp1mac(j),k,whichpflag)))&&
3388  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),jm1mac(j),k,whichpflag)))
3389  ){
3390  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected2\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3391  // then average
3392  PLOOPSTARTEND(pl){
3393  MACP0A1(pv,i,j,k,pl)=AVG4_2(ptoavg,i,j,k,pl);
3394  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3395  }
3396  }
3398  //
3399  // 2 VALUES
3400  //
3402  else if( // but if "surrounded" by good values
3403  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i,jp1mac(j),k,whichpflag)))&&
3404  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i,jm1mac(j),k,whichpflag)))
3405  ){
3406  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected3\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3407  // then average
3408  PLOOPSTARTEND(pl){
3409  MACP0A1(pv,i,j,k,pl)=AVG2_1(ptoavg,i,j,k,pl);
3410  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3411  }
3412  }
3413  else if( // but if "surrounded" by good values
3414  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),j,k,whichpflag)))&&
3415  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),j,k,whichpflag)))
3416  ){
3417  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected4\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3418  // then average
3419  PLOOPSTARTEND(pl){
3420  MACP0A1(pv,i,j,k,pl)=AVG2_2(ptoavg,i,j,k,pl);
3421  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3422  }
3423  }
3424  else if( // but if "surrounded" by good values
3425  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),jp1mac(j),k,whichpflag)))&&
3426  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),jm1mac(j),k,whichpflag)))
3427  ){
3428  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected5\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3429  // then average
3430  PLOOPSTARTEND(pl){
3431  MACP0A1(pv,i,j,k,pl)=AVG2_3(ptoavg,i,j,k,pl);
3432  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3433  }
3434  }
3435  else if( // but if "surrounded" by good values
3436  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),jm1mac(j),k,whichpflag)))&&
3437  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),jp1mac(j),k,whichpflag)))
3438  ){
3439  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected6\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3440  // then average
3441  PLOOPSTARTEND(pl){
3442  MACP0A1(pv,i,j,k,pl)=AVG2_4(ptoavg,i,j,k,pl);
3443  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3444  }
3445  }
3447  //
3448  // SINGLE VALUES
3449  //
3451  else if( // but if "surrounded" by good value
3452  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),jp1mac(j),k,whichpflag)))
3453  ){
3454  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3455  // then ASSIGN
3456  PLOOPSTARTEND(pl){
3457  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,ip1mac(i),jp1mac(j),k,pl);
3458  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3459  }
3460  }
3461  else if( // but if "surrounded" by good value
3462  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),j,k,whichpflag)))
3463  ){
3464  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3465  // then ASSIGN
3466  PLOOPSTARTEND(pl){
3467  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,ip1mac(i),j,k,pl);
3468  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3469  }
3470  }
3471  else if( // but if "surrounded" by good value
3472  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,ip1mac(i),jm1mac(j),k,whichpflag)))
3473  ){
3474  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3475  // then ASSIGN
3476  PLOOPSTARTEND(pl){
3477  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,ip1mac(i),jm1mac(j),k,pl);
3478  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3479  }
3480  }
3481  else if( // but if "surrounded" by good value
3482  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i,jm1mac(j),k,whichpflag)))
3483  ){
3484  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3485  // then ASSIGN
3486  PLOOPSTARTEND(pl){
3487  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,i,jm1mac(j),k,pl);
3488  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3489  }
3490  }
3491  else if( // but if "surrounded" by good value
3492  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),jm1mac(j),k,whichpflag)))
3493  ){
3494  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3495  // then ASSIGN
3496  PLOOPSTARTEND(pl){
3497  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,im1mac(i),jm1mac(j),k,pl);
3498  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3499  }
3500  }
3501  else if( // but if "surrounded" by good value
3502  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),j,k,whichpflag)))
3503  ){
3504  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3505  // then ASSIGN
3506  PLOOPSTARTEND(pl){
3507  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,im1mac(i),j,k,pl);
3508  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3509  }
3510  }
3511  else if( // but if "surrounded" by good value
3512  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,im1mac(i),jp1mac(j),k,whichpflag)))
3513  ){
3514  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3515  // then ASSIGN
3516  PLOOPSTARTEND(pl){
3517  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,im1mac(i),jp1mac(j),k,pl);
3518  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3519  }
3520  }
3521  else if( // but if "surrounded" by good value
3522  (IFUTOPRIMNOFAILORFIXED(MACP0A1(lpflagfailorig,i,jp1mac(j),k,whichpflag)))
3523  ){
3524  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected7\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3525  // then ASSIGN
3526  PLOOPSTARTEND(pl){
3527  MACP0A1(pv,i,j,k,pl)=MACP0A1(ptoavg,i,jp1mac(j),k,pl);
3528  if(debugfail>=2) dualfprintf(fail_file,"uc2: pl=%d pv=%21.15g\n",pl,MACP0A1(pv,i,j,k,pl));
3529  }
3530  }
3531  else{
3532  return(1);
3533  }
3534 
3535  // reaches here if ok
3536  return(0);
3537 }
3538 
3539 
3540 
3541 
3542 
3543 #define NOGOODSTATIC 0
3544 #define NOGOODRESET 1
3545 #define NOGOODAVERAGE 2
3546 
3547 // no good values. Choices: STATIC, RESET to something, and AVERAGE failed (t-dt surrounding) values.
3548 #define TODONOGOOD NOGOODAVERAGE
3549 // 0=STATIC // model-independent, but really bad idea -- causes death of computation for accretion disks in jet region.
3550 // 1=RESET // model-dependent
3551 // 2=AVERAGE // model-independent -- probably best idea -- and then hope for the best.
3552 
3553 
3554 // as stated
3555 // 0 : pv
3556 // 1: pbackup
3557 #define WHICHPTOUSEWHENNOGOOD 0
3558 
3559 
3561 //static int fixup_nogood(int startpl, int endpl, int i, int j, int k, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR],FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom)
3562 static int fixup_nogood(int startpl, int endpl, int i, int j, int k, int doingmhd, PFTYPE mhdlpflag, PFTYPE radlpflag, FTYPE (*pv)[NSTORE2][NSTORE3][NPR],FTYPE (*ptoavg)[NSTORE2][NSTORE3][NPR],FTYPE (*pbackup)[NSTORE2][NSTORE3][NPR], struct of_geom *ptrgeom)
3563 {
3564  int pl,pliter;
3565  FTYPE prguess[NPR];
3566  FTYPE (*ptoavgwhennogood)[NSTORE2][NSTORE3][NPR];
3567  int ti,tj,tk,resetregion;
3568 
3569 
3570 
3571  prod0dualfprintf(debugfail>=2,fail_file,"uc2nogood: i=%d j=%d k=%d\n",i,j,k); // not too much
3572 
3573 
3574  // Determine which primitive to use to average when no good solution
3575  // exists around to average
3576  if(WHICHPTOUSEWHENNOGOOD==0){
3577  ptoavgwhennogood=ptoavg;
3578  }
3579  else if(WHICHPTOUSEWHENNOGOOD==1){
3580  ptoavgwhennogood=pbackup;
3581  }
3582 
3583 
3584  ti=startpos[1]+i;
3585  tj=startpos[2]+j;
3586  tk=startpos[3]+k;
3587 
3588 
3590  //
3591  // no good values. Choices: STATIC, RESET to something, and AVERAGE failed (t-dt surrounding) values.
3592  //
3594 
3595 
3597  //
3599  //
3601 
3602 #if(USERRESETREGION==1)
3603  // tj = 0,1,totalsize[2]-2,totalsize[2]-1 are reset region
3604  // ti<10 near BH is reset region
3605  // resetregion=(tj>=-2 && tj<=1 || tj>=totalsize[2]-2 && tj<=totalsize[2]+1) || (ti<10);
3606  resetregion=(tj<=1 || tj>=totalsize[2]-2) || (ti<10);
3607 #elif(USERRESETREGION==0)
3608  resetregion=0;
3609 #endif
3610 
3611 
3612 
3613  if(resetregion || TODONOGOOD==NOGOODRESET){// if no solution, revert to normal observer and averaged densities
3614 
3615  // model-dependent: assumes failures occur mostly in jet region near where matter is mostly freefalling near black hole where b^2/rho_0>>1
3616 
3617  if(debugfail>=2) dualfprintf(fail_file,"t=%21.15g : i=%d j=%d k=%d : utoprim corrected9\n",t,startpos[1]+i,startpos[2]+j,startpos[3]+k);
3618  // otherwise some surrounding solutions are also bad, so just keep static
3619  // keeping static can lead to large regions of high gamma that are static and unstable to interactions. Thus, reset static to normal observer flow for safety.
3620  // setting to normal observer for surrounding high gamma flows leads to large shocks and high internal energy.
3621  //
3622  // thus not sure what to do. (should have gotten correct U in first place! -- that's what you should do)
3623  //
3624  // limit_gamma? Could also reset v completely to normal observer
3625  // if(limit_gamma(0,1.0,MAC(pv,i,j,k),ptrgeom,-1)>=1)
3626  // FAILSTATEMENT("fixup.c:fixup_utoprim()", "limit_gamma()", 1);
3627 
3628  // average out densities
3629  for(pl=0;pl<=UU;pl++) MACP0A1(pv,i,j,k,pl)=0.5*(AVG4_1(ptoavgwhennogood,i,j,k,pl)+AVG4_2(ptoavgwhennogood,i,j,k,pl));
3630  // make velocity the normal observer
3631  set_atmosphere(0,WHICHVEL,ptrgeom,prguess);
3632  for(pl=U1;pl<=U3;pl++) MACP0A1(pv,i,j,k,pl)=prguess[pl];
3633  // average out things above field "pl"
3634  for(pl=B3+1;pl<NPR;pl++) MACP0A1(pv,i,j,k,pl)=0.5*(AVG4_1(ptoavgwhennogood,i,j,k,pl)+AVG4_2(ptoavgwhennogood,i,j,k,pl));
3635 
3636  }
3638  //
3640  //
3642  else if(TODONOGOOD==NOGOODAVERAGE){// if no solution, revert to normal observer and averaged densities
3643  // average out densities+velocity
3644 #if(GENERALAVERAGE==1)
3645  // use general average without regard to failure
3646  int useonlynonfailed=0; // any type of cell, failed or not, will be used in the average
3647  int numbndtotry=1;
3648  int maxnumbndtotry=1; //MAXNUMPFLAGBND; // choice smaller or equal to MAXNUMPFLAGBND
3649  int nogood=general_average(useonlynonfailed,numbndtotry,maxnumbndtotry,startpl, endpl, i, j, k, doingmhd, mhdlpflag, radlpflag, NULL ,pv,ptoavg,ptrgeom);
3650  // nogood will be 1
3651 #else
3652  PLOOPSTARTEND(pl) MACP0A1(pv,i,j,k,pl)=0.5*(AVG4_1(ptoavgwhennogood,i,j,k,pl)+AVG4_2(ptoavgwhennogood,i,j,k,pl)); // like simple average
3653 #endif
3654 
3655  }
3656  else if(TODONOGOOD==NOGOODSTATIC){// if no solution, revert to normal observer and averaged densities
3657  // don't change -- stay at previous timestep value (or whatever utoprim() left it as).
3658  }
3659  else{
3660  dualfprintf(fail_file,"No condition for failure in fixup_nogood()\n");
3661  myexit(348576346);
3662  }
3663 
3664  return(0);
3665 }
3666 
3667 
3668 
3669 
3671 static int superdebug_utoprim(FTYPE *pr0, FTYPE *pr, struct of_geom *ptrgeom, int whocalled)
3672 {
3673  int pl,pliter;
3674  struct of_state q;
3675  FTYPE Ui[NPR],Uf[NPR];
3676  FTYPE X[NDIM],V[NDIM];
3677  FTYPE ftemp;
3678  int failreturn;
3679  static FILE * super_fail_file;
3680  static int firsttime=1;
3681  int output;
3682  static int countoutput=0;
3683 
3684 #if(USEOPENMP)
3685  dualfprintf(fail_file,"Cannot Superdebug with OpenMP\n");
3686  myexit(45968546);
3687 #endif
3688 
3689 
3690  if(firsttime){
3691  super_fail_file=fopen("superdebug.out","wt");
3692  if(super_fail_file==NULL){
3693  dualfprintf(fail_file,"Cannot open superdebug.out\n");
3694  myexit(1);
3695  }
3696  countoutput=0;
3697  }
3698 
3699  if(whocalled==-1){
3700  // then only output if every so often, randomly in step
3701  if(ranc(0,0)>0.99) output=1;
3702  else output=0;
3703  }
3704  else output=1;
3705 
3706  if(output){
3707  // before any changes
3708  failreturn=get_state(pr0,ptrgeom,&q);
3709  if(failreturn>=1) dualfprintf(fail_file,"get_state(1) failed in fixup.c, why???\n");
3710  failreturn=primtoU(UDIAG,pr0,&q,ptrgeom,Ui, NULL);
3711  if(failreturn>=1) dualfprintf(fail_file,"primtoU(1) failed in fixup.c, why???\n");
3712 
3713  // after any changes
3714  failreturn=get_state(pr,ptrgeom,&q);
3715  if(failreturn>=1) dualfprintf(fail_file,"get_state(2) failed in fixup.c, why???\n");
3716  failreturn=primtoU(UDIAG,pr,&q,ptrgeom,Uf, NULL);
3717  if(failreturn>=1) dualfprintf(fail_file,"primtoU(2) failed in fixup.c, why???\n");
3718 
3719 
3720  coord_ijk(ptrgeom->i, ptrgeom->j, ptrgeom->k, ptrgeom->p, X);
3721  bl_coord_ijk(ptrgeom->i, ptrgeom->j, ptrgeom->k, ptrgeom->p, V);
3722 
3723 
3724  // used to determine nature of pre and post failure quantities
3725  fprintf(super_fail_file,"%21.15g %ld %d %d %d ",t,realnstep,steppart,numstepparts,whocalled);
3726  fprintf(super_fail_file,"%21.15g %21.15g %21.15g %d %d %d ",V[1],V[2],V[3],startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k);
3727  PLOOP(pliter,pl) fprintf(super_fail_file,"%21.15g %21.15g %21.15g %21.15g ",pr0[pl],pr[pl],Ui[pl],Uf[pl]);
3728  fprintf(super_fail_file,"\n");
3729  if(!(countoutput%1000)) fflush(super_fail_file);
3730  countoutput++;
3731  }
3732 
3733 
3734 
3735  firsttime=0;
3736 
3737  return(0);
3738 }
3739 
3741 int set_density_floors_default(struct of_geom *ptrgeom, FTYPE *pr, FTYPE *prfloor, FTYPE *prceiling)
3742 {
3743  struct of_state q;
3744  FTYPE U[NPR];
3745  FTYPE bsq;
3746 
3747  if(rescaletype==2){
3748  // to best conserve E and L along magnetic field lines
3749  if (get_state(pr, ptrgeom, &q) >= 1)
3750  FAILSTATEMENT("fixup.c:set_density_floors()", "get_state() dir=0", 1);
3751 
3752  MYFUN(primtoU(UDIAG,pr, &q, ptrgeom, U, NULL),"fixup.c:set_density_floors()", "primtoU()", 1);
3753  }
3754 
3755  if(rescaletype==4||rescaletype==5){
3756  if(bsq_calc(pr,ptrgeom,&bsq)>=1){
3757  dualfprintf(fail_file,"bsq_calc:bsq_calc: failure\n");
3758  return(1);
3759  }
3760  }
3761 
3762  set_density_floors_default_alt(ptrgeom, &q, pr, U, bsq, prfloor, prceiling);
3763 
3764  return(0);
3765 }
3766 
3768 int set_density_floors_default_alt(struct of_geom *ptrgeom, struct of_state *q, FTYPE *pr, FTYPE *U, FTYPE bsq, FTYPE *prfloor, FTYPE *prceiling)
3769 {
3770  FTYPE Upbinf[NPR];
3771  FTYPE r,th,X[NDIM],V[NDIM];
3772  int pl,pliter;
3773  int i=ptrgeom->i,j=ptrgeom->j,k=ptrgeom->k,p=ptrgeom->p;
3774 
3775  coord_ijk(ptrgeom->i, ptrgeom->j, ptrgeom->k, ptrgeom->p, X);
3776  bl_coord_ijk(ptrgeom->i, ptrgeom->j, ptrgeom->k, ptrgeom->p, V);
3777  r=V[1];
3778  th=V[2];
3779 
3780  // default
3781  prceiling[RHO]=BIG;
3782  prceiling[UU]=BIG;
3783 
3784 
3785  if(PRAD0>=0.0) prfloor[PRAD0]=ERADLIMIT;
3786 
3788  // scaling functions
3790  if(1){ // choice
3791  if(rescaletype==0){
3792  // to be like Bondi
3793 
3794  // even if d/dt->0 and d/dphi->0, this doesn't conserve E and L along magnetic flux lines in the funnel region. This is bad!
3795  prfloor[RHO] = prfloorcoef[RHO]*pow(r, -1.5);
3796  prfloor[UU] = prfloorcoef[UU]*pow(r,-2.5);
3797  }
3798  else if(rescaletype==1){
3799  // to conserve E and L along magnetic lines, have b^2/\rho\sim const.
3800  prfloor[RHO] = prfloorcoef[RHO]*pow(r, -2.7);
3801  prfloor[UU] = prfloorcoef[UU]*pow(r,-2.7) ;
3802  }
3803  else if(rescaletype==2){
3804  // only set absolute limits and let density be set later
3805 
3806  // absolute limits determined by what density contrast can be handled by flux calculation. This is at least limited by machine precision, but more likely an instability is generated for some ratio of densities that's much smaller than machine precision.
3807 
3808  // we should fix absolute floor so that this point is not too much different than surrounding points.
3809  // this is difficult because process depends on how done, so just set reasonable minimum
3810 
3811  // Bondi like
3812  // coefficient should be small enough so that at outer radius the energy per baryon at infinity limit of (say) 100 can be maintained (b^2 \sim 0.01 r^{-2.7} for \rho=1 density maximum)
3813  // these will do for rout=10^4
3814  // prfloor[RHO] = 1E-12*pow(r, -1.5);
3815  //prfloor[UU] = 1E-14*prfloor[RHO]/r ;
3816 
3817 
3818 
3819 
3820  // now have U[UU] and U[PH]
3821  // note that U[UU]/(gdet*rho*u^t) is conserved along field lines, even in non-ideal MHD, where A_{\phi} is still a good stream function in non-ideal MHD.
3822  // same in terms of U[PH]
3823  // this is really a coordinate dependent quantity, but if field lines connect to infinity, then this is the same at infinity.
3824 
3825  // Conserved quantity per baryon (or rest-mass unit)
3826  // PALLLOOP(k) Upbinf=U[k]/(ptrgeom->gdet * pr[RHO]*(q.ucon[TT]));
3827  //Upbinf[UU]*=-1.0; // time component has - sign in this -+++ signature code
3828 
3829  // could inject mass or enthalpy, we choose mass for now since rho>h typically (except at very edge of torus)
3830  prfloor[RHO]=-U[UU]/(ptrgeom->gdet * GAMMAMAX * (q->ucon[TT]));
3831  prfloor[UU]=prfloor[RHO]*0.01; // cold injection
3832 
3833  }
3834  else if(rescaletype==3){
3835  // for dipole
3836  prfloor[RHO] = prfloorcoef[RHO]*pow(r/Rin, -5);
3837  prfloor[UU] = prfloorcoef[UU]*pow(r/Rin,-6) ;
3838  }
3839  else if(rescaletype==4||rescaletype==5){
3840  // for jet injection with maximum b^2/rho and b^2/u and maximum u/rho
3841 
3842  // below uses max of present u and floor u since present u may be too small (or negative!) and then density comparison isn't consistent with final floor between u and rho
3843 
3844  if(0 && RESTARTMODE==1){ // not on by default // choose
3845  // temporarily used to restart if cleaned field or increased resolution of field, because in high b^2/rho or b^2/u regions, the field dissipation due to small-scale structure in the field leads to heating that can become relativistic and disrupt the solution
3846  // Then also temporarily set UORHOLIMIT to 1.0 or some limiting thing
3847  FTYPE UORHOLIMITTEMP=0.5; // choose
3848  FTYPE TRESTART=5930; // choose
3849  FTYPE TRESTARTE=5921; // choose
3850  FTYPE BSQORHOLIMITTEMP=BSQORHOLIMIT*2.0;
3851  int POLESIZEE=8;
3852  int POLESIZE=3;
3853  if(t<TRESTARTE && ISSPCMCOORD(MCOORD) && (startpos[2]+j<POLESIZEE || startpos[2]+j>totalsize[2]-1-POLESIZEE)){
3854  // temporarily allow much higher field due to very early adjustments in field near pole. This avoids dumping mass into the pole at learly times.
3855  // But don't let u_g respond to field at all
3856  prfloor[RHO]=MAX(bsq/BSQORHOLIMITTEMP,SMALL);
3857  prfloor[UU]=MAX(MIN(pr[UU],UORHOLIMITTEMP*prfloor[RHO]),SMALL);
3858  }
3859  else if(t<TRESTART){
3860  // if(t<TRESTARTE && ISSPCMCOORD(MCOORD) && (startpos[2]+j<=1 || startpos[2]+j>=totalsize[2]-2)){
3861  // // don't allow floor injection of mass density related to u/rho during very early phase
3862  // prfloor[RHO]=MAX(bsq/BSQORHOLIMIT);
3863  // prfloor[UU]=MIN(pr[UU],UORHOLIMITTEMP*prfloor[RHO]);
3864  // }
3865  // else{
3866  // }
3867  // don't allow floor injection of mass density related to u/rho during very early phase
3868  prfloor[RHO]=MAX(bsq/BSQORHOLIMIT,SMALL);
3869  prfloor[UU]=MAX(MIN(pr[UU],UORHOLIMITTEMP*prfloor[RHO]),SMALL);
3870  }
3871  else if(ISSPCMCOORD(MCOORD) && (startpos[2]+j<POLESIZE || startpos[2]+j>totalsize[2]-1-POLESIZE)){
3872  prfloor[RHO]=MAX(bsq/BSQORHOLIMIT,SMALL);
3873  // still limit u near pole
3874  prfloor[UU]=MAX(MIN(pr[UU],UORHOLIMITTEMP*prfloor[RHO]),SMALL);
3875  //prceiling[UU]=MAX(prfloor[UU],MIN(prceiling[UU],UORHOLIMIT*MAX(pr[RHO],prfloor[RHO])));
3876  }
3877  else{ // NORMAL CASE when restarting,etc.
3878  prfloor[RHO]=MAX(bsq/BSQORHOLIMIT,SMALL);
3879  prfloor[UU]=MAX(bsq/BSQOULIMIT,zerouuperbaryon*MAX(prfloor[RHO],SMALL));
3880  // prfloor[UU]=MAX(MIN(MAX(pr[UU],prfloor[UU]),UORHOLIMIT*prfloor[RHO]),SMALL);
3881  prceiling[UU]=MAX(prfloor[UU],MIN(prceiling[UU],UORHOLIMIT*MAX(pr[RHO],prfloor[RHO])));
3882 
3883  }// end NORMAL else conditional
3884  }
3885  else{ // FULLY NORMAL CASE
3886  prfloor[RHO]=MAX(bsq/BSQORHOLIMIT,SMALL);
3887  prfloor[UU]=MAX(bsq/BSQOULIMIT,zerouuperbaryon*MAX(prfloor[RHO],SMALL));
3888  // prfloor[UU]=MAX(MIN(MAX(pr[UU],prfloor[UU]),UORHOLIMIT*prfloor[RHO]),SMALL);
3889  prceiling[UU]=MAX(prfloor[UU],MIN(prceiling[UU],UORHOLIMIT*MAX(pr[RHO],prfloor[RHO])));
3890 
3891  if(rescaletype==5){//WALD
3892  if(1){
3893  // do nothing, so constant bsq/rho
3894  }
3895  if(0){
3896  if(r>500.0){
3897  prfloor[RHO]*=pow(500,-1.5);
3898  prfloor[UU]*=pow(500,-2.5);
3899  }
3900  else{
3901  prfloor[RHO]*=(pow(r,-1.5)+pow(500,-1.5));
3902  prfloor[UU]*=(pow(r,-2.5)+pow(500,-2.5));
3903  }
3904  }
3905  if(0){
3906  FTYPE R=r*sin(th);
3907  FTYPE Z=fabs(r*cos(th));
3908  if(Z>500.0){
3909  prfloor[RHO]*=pow(500,-1.5);
3910  prfloor[UU]*=pow(500,-2.5);
3911  }
3912  else{
3913  prfloor[RHO]*=pow(Z,-1.5);
3914  prfloor[UU]*=pow(Z,-2.5);
3915  }
3916  }
3917  if(0){ // WALD TEST
3918  FTYPE R=r*sin(th);
3919  FTYPE Z=fabs(r*cos(th));
3920  prfloor[RHO]*=MIN(1.0/(pow(Z,1.5)*pow(R,-1.5)),1.0);
3921  prfloor[UU]*=MIN(1.0/(pow(Z,2.5)*pow(R,-2.5)),1.0);
3922  }
3923 
3924  }// end rescapetype==5
3925  }// else NORMAL case
3926 
3927 
3928 
3929  }// end rescaletype==4 || rescaletype==5
3930  }
3931  else{
3932  prfloor[RHO] = RHOMIN*pow(r, -2.0);
3933  prfloor[UU] = UUMIN*prfloor[RHO] ;
3934  }
3935 
3936  // KORALTODO: Maybe implement floor to ERAD relative to other energy densities like how handle UU and BSQ relative to RHO.
3937 
3938 
3939 
3940 
3941 
3942 
3943  // some old attempts
3944  /*
3945  if(0){ // choice
3946  ftempA=(RHOMAX+RHOMIN)*0.5/RHOMIN;
3947  ftempB=(RHOMAX-RHOMIN)*0.5/RHOMIN;
3948  // choice
3949  if(1) rhotscal = ftempA+ftempB*cos(2.0*M_PI*X[2]);
3950  else rhotscal = ftempA+ftempB*cos(2.0*M_PI*th);
3951  ftempA=(UUMAX+UUMIN)*0.5/UUMIN;
3952  // choice (make same as above)
3953  ftempB=(UUMAX-UUMIN)*0.5/UUMIN;
3954  if(1) uutscal = ftempA+ftempB*cos(2.0*M_PI*X[2]);
3955  else uutscal = ftempA+ftempB*cos(2.0*M_PI*th);
3956  }
3957 
3958  // else{
3959  if(1){
3960  rhotscal = 1.0;
3961  uutscal = 1.0;
3962  }
3963 
3964 
3965  prfloor[UU] = UUMIN*uurscal*uutscal;
3966  prfloor[RHO] = RHOMIN*rhorscal*rhotscal;
3967  */
3968 
3969 
3970  return(0);
3971 }
3972 
3973 
3974 
3975 #define FLOORDAMPFRAC (0.1)
3976 #define NUMBSQFLAGS 5
3977 
3979 int get_bsqflags(int stage, FTYPE (*pv)[NSTORE2][NSTORE3][NPR])
3980 {
3981  int i,j,k;
3982  FTYPE bsq;
3983  struct of_state q;
3984  FTYPE gamma,X[NDIM],V[NDIM];
3985  FTYPE qsq;
3986  FTYPE prfloor[NPR];
3987  PFTYPE flags[NUMBSQFLAGS]={0};
3988  int limgen;
3989  struct of_geom geomdontuse;
3990  struct of_geom *ptrgeom=&geomdontuse;
3991  int loc=CENT;
3992 
3993 
3994 
3995 
3996  // if((CHECKSOLUTION==0)&&(LIMADJUST==0)&&(FLUXADJUST==0)) return(0); // otherwise do it
3997  // fixup_checksolution() only uses failure flag right now
3998  if((LIMADJUST==0)&&(FLUXADJUST==0)) return(0); // otherwise do it
3999 
4000 
4001 
4002  // temporary hack
4003  limgen=MAX(MAX(lim[1],lim[2]),lim[3]); // not reached if((LIMADJUST==0)&&(FLUXADJUST==0))
4004 
4005 
4006 
4007  COMPDQZLOOP { // over range wspeed and dq are computed // OPENMPOPTMARK: Could optimize this, but not using it currently
4008 
4009  get_geometry(i, j, k, loc, ptrgeom);
4010 
4011 
4012 #if(DOEVOLVERHO)
4013  // b^2
4014  if (get_state(MAC(pv,i,j,k), ptrgeom, &q) >= 1)
4015  FAILSTATEMENT("fixup.c:get_bsqflags()", "get_state()", 1);
4016  bsq = dot(q.bcon, q.bcov);
4017  // initial
4018  GLOBALMACP0A1(pflag,i,j,k,FLAGBSQORHO)=0;
4019 
4020  // now do checks 10/31/2003 : constants fixed based upon accretion
4021  // models and locations of disk, corona, and funnel (b^2/rho>1)
4022 
4023  // b^2/\rho
4024  if(bsq/MACP0A1(pv,i,j,k,RHO)>BSQORHOLIMIT) flags[0]=2;
4025  else if(bsq/MACP0A1(pv,i,j,k,RHO)>0.9*BSQORHOLIMIT) flags[0]=1;
4026  else flags[0]=0;
4027 
4028 #endif
4029 
4030  // KORALTODO: Maybe implement floor to ERAD relative to other energy densities like how handle UU and BSQ relative to RHO.
4031 
4032 
4033 #if(DOEVOLVEUU)
4034  // b^2/u
4035 
4036  if(bsq/MACP0A1(pv,i,j,k,UU)>BSQOULIMIT) flags[3]=2;
4037  else if(bsq/MACP0A1(pv,i,j,k,UU)>0.9*BSQOULIMIT) flags[3]=1;
4038  else flags[3]=0;
4039 #endif
4040 
4041 
4042 
4043 #if(WHICHVEL==VELREL4)
4044  // gamma
4045  if(gamma_calc(MAC(pv,i,j,k),ptrgeom,&gamma,&qsq)>=1){
4046  dualfprintf(fail_file,"gamma calc failed: get_bsqflags\n");
4047  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4048  return (1);
4049  }
4050  // \gamma relative to 4-velocity
4051  if(gamma>2.0*GAMMADAMP) flags[1]=2;
4052  else if(gamma>GAMMADAMP) flags[1]=1;
4053  else flags[1]=0;
4054 #endif
4055  // these density mod on limiters may be too much diffusivity in otherwise ok regions
4056 
4057 
4058 #if(0)
4059  // density floors
4060  set_density_floors(ptrgeom,MAC(pv,i,j,k),prfloor,prceiling);
4061  // rho/rho_{fl}
4062  // GODMARK, 0.1 here
4063  if(prfloor[RHO]/MACP0A1(pv,i,j,k,RHO)>FLOORDAMPFRAC) flags[2]=2;
4064  else if(prfloor[RHO]/MACP0A1(pv,i,j,k,RHO)>0.1*FLOORDAMPFRAC) flags[2]=1;
4065  else flags[2]=0;
4066 
4067  // u/u_{fl}
4068 
4069  if(prfloor[UU]/MACP0A1(pv,i,j,k,UU)>FLOORDAMPFRAC) flags[4]=2;
4070  else if(prfloor[UU]/MACP0A1(pv,i,j,k,UU)>0.1*FLOORDAMPFRAC) flags[4]=1;
4071  else flags[4]=0;
4072 #endif
4073 
4074 
4075  // now check our flag state
4076  GLOBALMACP0A1(pflag,i,j,k,FLAGBSQORHO)=flags[0];
4077  GLOBALMACP0A1(pflag,i,j,k,FLAGBSQOU)=flags[3];
4078 
4079 
4080 #if(LIMADJUST>0)
4081  // now check our flag state
4082  if((flags[0]==2)||(flags[1]==2)||(flags[2]==2)||(flags[3]==2)||(flags[4]==2)){ GLOBALMACP0A1(pflag,i,j,k,FLAGREALLIM)=limgen-1; }
4083  else if((flags[0]==1)||(flags[1]==1)||(flags[2]==1)||(flags[3]==1)||(flags[4]==1)){ GLOBALMACP0A1(pflag,i,j,k,FLAGREALLIM)=limgen-1; }
4084  else{GLOBALMACP0A1(pflag,i,j,k,FLAGREALLIM)=limgen;}
4085  if(GLOBALMACP0A1(pflag,i,j,k,FLAGREALLIM)<0) GLOBALMACP0A1(pflag,i,j,k,FLAGREALLIM)=0;
4086 #endif
4087 
4088 #if(FLUXADJUST>0)
4089  // now check our flag state
4090  if((flags[0]==2)||(flags[1]==2)||(flags[2]==2)||(flags[3]==2)||(flags[4]==2)){ GLOBALMACP0A1(pflag,i,j,k,FLAGREALFLUX)=fluxmethod[RHO]-1;}
4091  else if((flags[0]==1)||(flags[1]==1)||(flags[2]==1)||(flags[3]==1)||(flags[4]==1)){ GLOBALMACP0A1(pflag,i,j,k,FLAGREALFLUX)=fluxmethod[RHO]; }
4092  else{GLOBALMACP0A1(pflag,i,j,k,FLAGREALFLUX)=fluxmethod[RHO];}
4093  if(GLOBALMACP0A1(pflag,i,j,k,FLAGREALFLUX)<0) GLOBALMACP0A1(pflag,i,j,k,FLAGREALFLUX)=0;
4094 #endif
4095 
4096 
4097  }
4098  return(0);
4099 }
4100 
4101 
4102 
4103 // whether to limit gamma inside ergosphere
4104 #define GAMMAERGOLIMIT 0
4105 
4106 // whether to conserve (at least) D=\rho_0 u^t when modifying \gamma
4107 // risky to assume D=rho_0 u^t conserved when limiting \gamma because \gamma may be large due to error simply in T^t_\nu evolution alone
4108 // So D evolution may be normal and more accurate, and so effectively error in T^t_\nu leads to large u^t but D changes little
4109 // so this fix would add a great deal of rest-mass
4110 // So for now just limit velocity ignoring all conservation laws
4111 #define DO_CONSERVE_D 0
4112 
4114 int limit_gamma(int docorrectucons, FTYPE gammamax, FTYPE gammamaxrad, FTYPE*pr, FTYPE *ucons, struct of_geom *ptrgeom,int finalstep)
4115 {
4116  FTYPE f,gamma,pref;
4117  FTYPE qsq;
4118  FTYPE alpha;
4119  FTYPE radgamma,radqsq;
4120  FTYPE pr0[NPR];
4121  int pl,pliter;
4122  FTYPE realgammamax,realgammamaxrad;
4123  FTYPE r,X[NDIM],V[NDIM];
4124  int didchange;
4125  FTYPE uu0,uu0max;
4126  int i=ptrgeom->i;
4127  int j=ptrgeom->j;
4128  int k=ptrgeom->k;
4129  int loc=ptrgeom->p;
4130 
4131  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
4132  // dualfprintf(fail_file,"inside limit_gamma(): finalstep=%d nstep=%ld steppart=%d\n",finalstep,nstep,steppart);
4133  // }
4134 
4135  // assume didn't change primitives
4136  didchange=0;
4137 
4138 
4139 
4141  //
4142  // Ad-hoc ergo fix for force-free black hole problem (enabled very rarely)
4143  //
4145 #if(GAMMAERGOLIMIT)
4146  coord_ijk(i,j,k,loc,X);
4147  bl_coord_ijk(i,j,k,loc,V);
4148  r=V[1];
4149 
4150  // force flow to not move too fast inside ergosphere
4151  if(r<2) realgammamax=3;
4152  else realgammamax=GAMMAMAX;
4153  realgammamaxrad=GAMMAMAXRAD;
4154 #else
4155  realgammamax=gammamax;
4156  realgammamaxrad=gammamaxrad;
4157  if(realgammamax<=1.0 && realgammamaxrad<=1.0) return(0); // nothing to do
4158 #endif
4159 
4160 
4161 
4162 
4163 
4164 
4166  //
4167  // Get \gamma
4168  //
4170  //PALLLOOP(pl){ dualfprintf(fail_file,"i=%d j=%d k=%d pr[%d]=%21.15g\n",startpos[1]+i,startpos[2]+j,startpos[3]+k,pl,MAC(pv,i,j,k));}
4171  if(gamma_calc(pr,ptrgeom,&gamma,&qsq)>=1){
4172  dualfprintf(fail_file,"limit_gamma: gamma calc failed\n");
4173  dualfprintf(fail_file,"i=%d j=%d k=%d oldgamma=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,gamma);
4174  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4175  return (1);
4176  }
4177 
4178  if(EOMRADTYPE!=EOMRADNONE){
4179  if(gamma_calc(&pr[URAD1-U1],ptrgeom,&radgamma,&radqsq)>=1){
4180  dualfprintf(fail_file,"limit_gamma: gamma calc failed: rad\n");
4181  dualfprintf(fail_file,"i=%d j=%d k=%d : rad : oldgamma=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,gamma);
4182  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4183  return (1);
4184  }
4185  }
4186 
4187 
4188 
4190  //
4191  // set pre-changed primitive
4192  //
4194  PALLLOOP(pl) pr0[pl]=pr[pl];
4195 
4196 
4197 
4199  //
4200  // If \gamma>\gammamax, then force \gamma=\gammamax
4201  //
4203  if((gamma > realgammamax && (gamma!=1.0))) {
4204 
4205  // rescale velocities to reduce gamma to realgammamax
4206  pref=(realgammamax*realgammamax - 1.)/(gamma*gamma - 1.);
4207 
4208  if(debugfail>=3){ // special >=3 since often called when floor or fixup
4209  dualfprintf(fail_file,"nstep=%ld steppart=%d t=%21.15g :: i=%d j=%d k=%d :: pref=%21.15g oldgamma=%21.15g realgammamax=%21.15g\n",nstep,steppart,t,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,pref,gamma,realgammamax);
4210  }
4211 
4212  if(pref<0.0){
4213  dualfprintf(fail_file,"limit_gamma: pref calc failed pref=%21.15g\n",pref);
4214  dualfprintf(fail_file,"i=%d j=%d k=%d oldgamma=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,gamma);
4215  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4216  return (1);
4217  }
4218 
4219  f = sqrt(pref);
4220  pr[U1] *= f ;
4221  pr[U2] *= f ;
4222  pr[U3] *= f ;
4223 
4224 
4225 #if(DO_CONSERVE_D)
4226  // alpha = alpha = 1./sqrt(-ptrgeom->gcon[GIND(TT,TT)]) ;
4227  //uu0old=gamma/alpha;
4228  // force conservation of particle number
4229  pr[RHO] = pr0[RHO]*gamma/realgammamax; // can do this since alpha is constant and so cancels
4230 #endif
4231 
4232  gamma=gammamax; // reset gamma for next check
4233  didchange=1; // indicate did change primitive
4234  }
4235 
4236 
4237 
4238  // KORAL:
4239  if(EOMRADTYPE!=EOMRADNONE){
4240 
4241  if((radgamma > realgammamaxrad && (radgamma!=1.0))) {
4242 
4243  // rescale velocities to reduce radgamma to realgammamaxrad
4244  pref=(realgammamaxrad*realgammamaxrad - 1.)/(radgamma*radgamma - 1.);
4245 
4246  if(debugfail>=3){ // special >=3 since often called when floor or fixup
4247  dualfprintf(fail_file,"nstep=%ld steppart=%d t=%21.15g :: i=%d j=%d k=%d :: pref=%21.15g oldradgamma=%21.15g realgammamaxrad=%21.15g\n",nstep,steppart,t,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,pref,radgamma,realgammamaxrad);
4248  }
4249 
4250  if(pref<0.0){
4251  dualfprintf(fail_file,"limit_gamma: pref calc failed pref=%21.15g\n",pref);
4252  dualfprintf(fail_file,"i=%d j=%d k=%d oldgamma=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,radgamma);
4253  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4254  return (1);
4255  }
4256 
4257  f = sqrt(pref);
4258  pr[URAD1] *= f ;
4259  pr[URAD2] *= f ;
4260  pr[URAD3] *= f ;
4261 
4262 
4263  radgamma=gammamaxrad; // reset radgamma for next check
4264  didchange=1; // indicate did change primitive
4265  }
4266  }
4267 
4268 
4269 
4271  //
4272  // limiting u^t makes no sense except as an indicator of when in difficult regime
4273  //
4275 #if(0)
4276  // limit u^t too since maybe alpha very small
4277  //alpha = 1./sqrt(-ptrgeom->gcon[GIND(TT,TT)]) ;
4278  alpha = ptrgeom->alphalapse;
4279  uu0=gamma/alpha;
4280  uu0max=realgammamax;
4281  // since alpha is always >=1, then limit on uu0 always overrides limit on gamma?
4282  // here realgammamax is u^t not u^t\alpha
4283  if((uu0 > uu0max && (uu0!=1.0))) {
4284 
4285  //dualfprintf(fail_file,"gamma=%21.15g realgammamax=%21.15g\n",gamma,gammamax);
4286 
4287  if(debugfail>=2) dualfprintf(fail_file,"i=%d j=%d k=%d oldgamma=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,gamma);
4288  // rescale velocities to reduce gamma to realgammamax
4289  pref=(uu0max*uu0max*alpha*alpha - 1.)/(gamma*gamma - 1.);
4290  if(pref<0.0){
4291  dualfprintf(fail_file,"limit_gamma: pref calc failed pref=%21.15g\n",pref);
4292  dualfprintf(fail_file,"i=%d j=%d k=%d oldgamma=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,gamma);
4293  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4294  return (1);
4295  }
4296 
4297  f = sqrt(pref);
4298  pr[U1] *= f ;
4299  pr[U2] *= f ;
4300  pr[U3] *= f ;
4301 
4302 #if(DO_CONSERVE_D)
4303  // alpha = alpha = 1./sqrt(-ptrgeom->gcon[GIND(TT,TT)]) ;
4304  //uu0old=gamma/alpha;
4305  // force conservation of particle number
4306  pr[RHO] = pr0[RHO]*uu0/uu0max;
4307 #endif
4308 
4309  didchange=1;
4310  }
4311 #endif
4312 
4313 
4314 
4315 
4317  //
4318  // Account for changes in conserved quantities via changes in: \rho_0 and pr[U1..U3]
4319  //
4321  if(didchange){
4322  FTYPE prdiag[NPR];
4323  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4324  int doingmhdfixup=1;
4325  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
4326  // dualfprintf(fail_file,"LIMITGAMMABEFORE: steppart=%d nstep=%ld\n",steppart,nstep);
4327  // }
4328  diag_fixup(docorrectucons,prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTLIMITGAMMAACT);
4329  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4330  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
4331  // dualfprintf(fail_file,"LIMITGAMMAAFTER: steppart=%d nstep=%ld\n",steppart,nstep);
4332  // }
4333 
4334  return(-1);// indicates did change primitive
4335  }
4336 
4337 
4338  return(0); // indicates didn't change anything
4339 }
4340 
4341 
4342 
4343 
4344 
4345 
4346 
4347 // check_pr() is purely 2D function
4348 
4349 #define UTLIMIT (50.0) // limit of u^t given no other info and need to fix u
4350 #define UTFIX (utobs) // if failed u^t, then fix to this level to keep normal, or use local value as desired value
4351 #define GRADIENTFACTOR (.001) // how to set?
4352 
4356 int check_pr(FTYPE *pr,FTYPE *prmodel, FTYPE *ucons, struct of_geom *ptrgeom,int modelpos, int finalstep)
4357 {
4358 
4359 #if(WHICHVEL==VEL3)
4360  int failedcheck;
4361  FTYPE ucon[NPR],uconmodel[NPR];
4362  FTYPE others[NUMOTHERSTATERESULTS],othersmodel[NUMOTHERSTATERESULTS];
4363  FTYPE prold[NPR],probs[NPR];
4364  FTYPE gradient[NDIM],normsq;
4365  int trialcount,ntrials;
4366  int i,j,k;
4367  int pl,pliter;
4368  FTYPE lastuttdiscr,uttdiscr0,utobs;
4369  FTYPE dampfactor,dampfactorchange;
4370  FTYPE newerr,olderr;
4371  int method;
4372  struct of_geom modelgeomdontuse;
4373  struct of_geom *ptrmodelgeom=&modelgeomdontuse;
4374  int idel,jdel,kdel;
4375  FTYPE realutlimit,realdiscrlimit;
4376  FTYPE modeldiscr;
4377  int utinterp;
4378  FTYPE toldiscr;
4379  int modeli,modelj,modelk;
4380  int bctype;
4381  FTYPE pr0[NPR];
4382  int loc=CENT;
4383 
4384 
4385  if(modelpos==-100){ // then utoprim called us from usrfun
4386  modelpos=0;
4387  ntrials=30; // don't try so hard since failure is more likely, leads to static solution
4388  }
4389  else{
4390  ntrials=200; // try really hard since using observer as solution is not fun
4391  }
4392  toldiscr=1.E-2;
4393  dampfactorchange=0.5;
4394  dampfactor=1.0;
4395  method=1; // 0=GRADIENTFACTOR 1=damp newton's method
4396  utinterp=0; // whether to fix interpolation (if bad) based upon a model pr
4397 
4398 
4399  if(method==1){
4400  // save old pr
4401  PALLLOOP(pl) probs[pl]=prold[pl]=pr[pl];
4402  }
4403 
4404  whocalleducon=1; // turn off failures
4405  if(ucon_calc(pr, ptrgeom, ucon,others) >= 1) ucon[TT]=1E30; // bad, so keep going
4406  uttdiscr0=lastuttdiscr=uttdiscr; // ucon_calc() set uttdiscr
4407  if(ucon[TT]<UTLIMIT) return(0); // good, so just continue calculations
4408 
4409 
4411  //
4412  // if here, need to fix
4413  //
4414  // set pre-primitive
4415  PALLLOOP(pl) pr0[pl]=pr[pl];
4416 
4417 
4418 
4419  if(modelpos==-2) return(1); // don't try to correct, just fail since ucon[TT] wasn't less than the limit (otherwise wouldn't reach here). Used to just check, no fix.
4420 
4421  if(modelpos==-3){
4422  modelpos=-1;
4423  bctype=1; // so bound_prim called us
4424  }
4425  else bctype=0; // non-bound call
4426 
4427 
4429  //
4430  // if we are here, original velocities need to be corrected
4431 
4432  // first find normal observer to get relevant u^t
4433  for(i=1;i<=3;i++){
4434  probs[U1+i-1] = ptrgeom->gcon[GIND(TT,i)]/ptrgeom->gcon[GIND(TT,TT)] ;
4435  }
4436  // ucon[TT] must be good for normal observer (?) hard to solve for u^t for normal observer in general
4437  // change of whocalleducon forces kill level check on normal observer
4438  whocalleducon=0;
4439  if(ucon_calc(probs, ptrgeom, ucon, others) >= 1){
4440  dualfprintf(fail_file,"Thought normal observer had to have good u^t!\n");
4441  return(1);
4442  }
4443  else utobs=ucon[TT];
4444  whocalleducon=1;
4445 
4446 
4447  if(utinterp&&(modelpos>=0)){ // use modelpos==-1 for no use of model
4448  // below for no interpolation but use of model
4449  if(modelpos==0){
4450  modeli=ptrgeom->i;
4451  modelj=ptrgeom->j;
4452  modelk=ptrgeom->k;
4453  ptrmodelgeom=ptrgeom;
4454  }
4455  // modelpos>=1 for interpolations in fluxcalc() (model value on center)
4456  else if(modelpos==1){
4457  if(ptrgeom->p==FACE1){ idel=1; jdel=0; kdel=0; }
4458  else if(ptrgeom->p==FACE2){ idel=0; jdel=1; kdel=0; }
4459  else if(ptrgeom->p==FACE3){ idel=0; jdel=0; kdel=1; }
4460  modeli=(ptrgeom->i) -idel;
4461  modelj=(ptrgeom->j) -jdel;
4462  modelk=(ptrgeom->k) -kdel;
4463  // then i-1,j is center position
4464  get_geometry(modeli,modelj,modelk,loc,ptrmodelgeom);
4465  }
4466  else if(modelpos==2){
4467  modeli=ptrgeom->i;
4468  modelj=ptrgeom->j;
4469  modelk=ptrgeom->k;
4470  // then i,j is center position
4471  get_geometry(modeli,modelj,modelk,loc,ptrmodelgeom);
4472  }
4473  // determine model u^t
4474  if(ucon_calc(prmodel, ptrmodelgeom, uconmodel, othersmodel) >= 1){
4475  // model no good
4476  if(bctype==0){
4477  dualfprintf(fail_file,"serious failure. On-grid values and fixed bc values used have u^t imaginary: modeli: %d modelj: %d uttdiscr: %21.15g\n",startpos[1]+modeli,startpos[2]+modelj,uttdiscr);
4478  whocalleducon=0; // turn on failures
4479  if (fail(i,j,k,loc,FAIL_UTCALC_DISCR) >= 1)
4480  return (1);
4481  }
4482  else uconmodel[TT]=realutlimit=1E30;
4483  // otherwise normal to sometimes encounter failure if using model in bc (which isn't currently)
4484  }
4485  else realutlimit=uconmodel[TT]; // model ut
4486  modeldiscr=uttdiscr;
4487 
4488  // upper limit (if model has large u^t, assume ok to have one)
4489  if(realutlimit>UTLIMIT) realutlimit=UTLIMIT;
4490  }
4491  else realutlimit=UTFIX; // no model, just fix based upon normal observer since no idea what is "ok" to have
4492 
4493  realdiscrlimit=1.0/(realutlimit*realutlimit);
4494  newerr=olderr=fabs(lastuttdiscr-realdiscrlimit)/realdiscrlimit;
4495 
4496 
4497  // LOOP
4498 
4499 
4500  // otherwise need to fix
4501  failedcheck=0;
4502 
4503  trialcount=0;
4504  while( ((newerr>toldiscr)&&(method==1)) ||((ucon[TT]>realutlimit)&&(method==0)) ){
4505  // see if we can fix things since outside limits
4506 
4507  // determine gradient
4508  normsq=0.0;
4509  for(i=1;i<=3;i++){
4510  gradient[i]=2.0*(ptrgeom->gcov[GIND(0,i)]);
4511  for(j=1;j<=3;j++){
4512  // note that ucon is the same as pr here since ucon_calc sets spatial terms to pr
4513  gradient[i]+=2.0*ucon[j]*ptrgeom->gcov[GIND(i,j)];
4514  }
4515  normsq+=gradient[i]*gradient[i];
4516  }
4517  // normalize gradient
4518  for(i=1;i<=3;i++){
4519  gradient[i]/=sqrt(normsq);
4520  }
4521  // save old pr and change new one
4522  if(method==0){
4523  for(i=1;i<=3;i++){
4524 
4525  pr[U1+i-1]-=gradient[i]*GRADIENTFACTOR*((FTYPE)(ntrials)+1.0)/((FTYPE)(ntrials)-(FTYPE)(trialcount)+1.0);
4526  //pr[U1+i-1]-=gradient[i]*GRADIENTFACTOR;
4527  }
4528  }
4529  else if(method==1){
4530  for(i=1;i<=3;i++){
4531  prold[U1+i-1]=pr[U1+i-1];
4532  if(realdiscrlimit-uttdiscr>0) pr[U1+i-1]-=gradient[i]*dampfactor;
4533  else pr[U1+i-1]+=gradient[i]*dampfactor;
4534  }
4535  }
4536  // get new ucon[TT], is it ok now?
4537  if(ucon_calc(pr, ptrgeom, ucon,others) >= 1) ucon[TT]=1E30; // bad bad, keep going
4538  newerr=fabs(uttdiscr-realdiscrlimit)/realdiscrlimit;
4539  if((method==1)&&(newerr>=olderr)){
4540  // then went too far (if going in right direction at all)
4541  dampfactor*=dampfactorchange;
4542  if(dampfactor<1E-10){
4543  if((fabs(ucon[TT]-realutlimit)/realutlimit)<0.5) break; // just be happy you got out alive
4544  else{
4545  failedcheck=1;
4546  if(debugfail>=1) dualfprintf(fail_file,"dumpfactor reached min\n");
4547  break;
4548  }
4549  }
4550  // revert to old pr and start again
4551  for(i=1;i<=3;i++){
4552  pr[U1+i-1]=prold[U1+i-1];
4553  }
4554  }
4555  else{
4556  trialcount++; // only iterate if good step
4557  olderr=newerr;
4558  }
4559  if(debugfail>=2) {
4560  if((myid==0)&&(ptrgeom->i==117)&&(ptrgeom->j==-1)){
4561  dualfprintf(fail_file,"trialcount=%d uttdiscr0=%21.15g uttdiscr=%21.15g newerr: %21.15g dampfactor=%21.15g\n",trialcount,uttdiscr0,uttdiscr,newerr,dampfactor);
4562  }
4563  }
4564  // even if not bad, could still be too large, so check
4565  if(trialcount==ntrials){
4566  if((fabs(ucon[TT]-realutlimit)/realutlimit)<0.5) break; // just be happy you got out alive
4567  else{
4568  failedcheck=1;
4569  if(debugfail>=1) dualfprintf(fail_file,"number of trials reached max\n");
4570  break;
4571  }
4572  }
4573  }
4574  whocalleducon=0; // turn back on failures
4575 
4576  if(failedcheck){
4577  if(debugfail>=1) dualfprintf(fail_file,"couldn't fix ucon[TT]=%21.15g newerr=%21.15g uttdiscr=%21.15g\n",ucon[TT],newerr,uttdiscr);
4578  if(debugfail>=1) dualfprintf(fail_file,"check_pr failure: t=%21.15g , couldn't fix ucon: i=%d j=%d k=%d p=%d ucon[TT]=%21.15g realutlimit=%21.15g uconmodel[TT]=%21.15g\n",t,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,ptrgeom->p,ucon[TT],realutlimit,uconmodel[TT]);
4579  if(debugfail>=1) dualfprintf(fail_file,"uttdiscr0=%21.15g uttdiscr=%21.15g realdiscrlimit=%21.15g modeldiscr=%21.15g dampfactor=%21.15g\n",uttdiscr0,uttdiscr,realdiscrlimit,modeldiscr,dampfactor);
4580  // will still run perhaps with UT>realutlimit, could stop it, but won't for now
4581  if(debugfail>=1){
4582  PALLLOOP(pl){
4583  dualfprintf(fail_file,"pr[%d]=%21.15g prmodel[%d]=%21.15g\n",pl,pr[pl],pl,prmodel[pl]);
4584  }
4585  if(debugfail>=1) dualfprintf(fail_file,"need better algorithm: check_pr failure: couldn't fix ucon: i=%d j=%d k=%d p=%d ucon[TT]=%21.15g\n",startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,ptrgeom->p,ucon[TT]);
4586  }
4587 
4588  // force to normal observer solution
4589  PALLLOOP(pl) pr[pl]=probs[pl];
4590  }
4591 
4592  // account for changes
4593  FTYPE prdiag[NPR];
4594  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4595  int doingmhdfixup=1;
4596  int docorrectucons=(DOENOFLUX != NOENOFLUX);
4597  diag_fixup(docorrectucons,prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTLIMITGAMMAACT);
4598  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4599 
4600 #endif
4601 
4602  return(0);
4603 }
4604 
4605 
4608 int inflow_check_4vel(int dir, FTYPE *pr, FTYPE *ucons, struct of_geom *ptrgeom, int finalstep)
4609 {
4610  int ii,jj,kk;
4611  int iin,iout;
4612  int jjn,jout;
4613  int kkn,kout;
4614  FTYPE pr0[NPR],prdiag[NPR];
4615  int pl,pliter;
4616 
4617 
4618  ii=ptrgeom->i;
4619  jj=ptrgeom->j;
4620  kk=ptrgeom->k;
4621 
4622 
4623  if(dir==1){
4624  // for dir==1
4625  if((ptrgeom->p==CENT)||(ptrgeom->p==FACE2)||(ptrgeom->p==FACE3)||(ptrgeom->p==CORN1) ){ iin=-1; iout=totalsize[1]; }
4626  else if((ptrgeom->p==FACE1)||(ptrgeom->p==CORN3)||(ptrgeom->p==CORN2) ){ iin=0; iout=totalsize[1]; }
4627  else{
4628  dualfprintf(fail_file,"dir=%d no such location: %d\n",dir,ptrgeom->p);
4629  myexit(1);
4630  }
4631  if(
4632  ((startpos[1]+ii<=iin)&&((BCtype[X1DN]==OUTFLOW || BCtype[X1DN]==HORIZONOUTFLOW))&&(pr[U1+dir-1] > 0.))
4633  ||((startpos[1]+ii>=iout)&&((BCtype[X1UP]==OUTFLOW || BCtype[X1UP]==HORIZONOUTFLOW))&&(pr[U1+dir-1] < 0.))
4634  ) {
4635  // set pre-primitive
4636  PALLLOOP(pl) pr0[pl]=pr[pl];
4637  pr[U1]=0;
4638 
4639  // account for changes
4640  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4641  int doingmhdfixup=1;
4642  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4643  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4644  }
4645  if(EOMRADTYPE!=EOMRADNONE&&(
4646  ((startpos[1]+ii<=iin)&&((BCtype[X1DN]==OUTFLOW || BCtype[X1DN]==HORIZONOUTFLOW))&&(pr[URAD1+dir-1] > 0.))
4647  ||((startpos[1]+ii>=iout)&&((BCtype[X1UP]==OUTFLOW || BCtype[X1UP]==HORIZONOUTFLOW))&&(pr[URAD1+dir-1] < 0.))
4648  )
4649  ) {
4650  // set pre-primitive
4651  PALLLOOP(pl) pr0[pl]=pr[pl];
4652  pr[URAD1]=0;
4653 
4654  // account for changes
4655  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4656  int doingmhdfixup=1;
4657  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4658  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4659  }
4660  if(
4661  ((startpos[1]+ii<=iin)&&(BCtype[X1DN]==FIXEDOUTFLOW)&&(pr[U1+dir-1] > 0.))
4662  ||((startpos[1]+ii>=iout)&&(BCtype[X1UP]==FIXEDOUTFLOW)&&(pr[U1+dir-1] < 0.))
4663  ) {
4664  // set pre-primitive
4665  PALLLOOP(pl) pr0[pl]=pr[pl];
4666  // then inflow according to Bondi-like atmosphere
4667  set_atmosphere(1,WHICHVEL,ptrgeom,pr);
4668 
4669  // below never really accounted for since on boundary zones
4670  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4671  int doingmhdfixup=1;
4672  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4673  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4674  }
4675  }
4676  else if(dir==2){
4677  // for dir==2
4678  if((ptrgeom->p==CENT)||(ptrgeom->p==FACE1)||(ptrgeom->p==FACE3)||(ptrgeom->p==CORN2) ){ jjn=-1; jout=totalsize[2]; }
4679  else if((ptrgeom->p==FACE2)||(ptrgeom->p==CORN1)||(ptrgeom->p==CORN3) ){ jjn=0; jout=totalsize[2]; }
4680  else{
4681  dualfprintf(fail_file,"dir=%d no such location: %d\n",dir,ptrgeom->p);
4682  myexit(1);
4683  }
4684  if(
4685  ((startpos[2]+jj<=jjn)&&(BCtype[X2DN]==OUTFLOW)&&(pr[U1+dir-1] > 0.))
4686  ||((startpos[2]+jj>=jout)&&(BCtype[X2UP]==OUTFLOW)&&(pr[U1+dir-1] < 0.))
4687  ) {
4688  // set pre-primitive
4689  PALLLOOP(pl) pr0[pl]=pr[pl];
4690  pr[U2]=0;
4691 
4692  // account for changes
4693  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4694  int doingmhdfixup=1;
4695  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4696  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4697  }
4698  if(EOMRADTYPE!=EOMRADNONE&&(
4699  ((startpos[2]+jj<=jjn)&&(BCtype[X2DN]==OUTFLOW)&&(pr[URAD1+dir-1] > 0.))
4700  ||((startpos[2]+jj>=jout)&&(BCtype[X2UP]==OUTFLOW)&&(pr[URAD1+dir-1] < 0.))
4701  )
4702  ) {
4703  // set pre-primitive
4704  PALLLOOP(pl) pr0[pl]=pr[pl];
4705  pr[URAD2]=0;
4706 
4707  // account for changes
4708  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4709  int doingmhdfixup=1;
4710  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4711  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4712  }
4713  }
4714  else if(dir==3){
4715  // for dir==3
4716  if((ptrgeom->p==CENT)||(ptrgeom->p==FACE2)||(ptrgeom->p==FACE3)||(ptrgeom->p==CORN3) ){ kkn=-1; kout=totalsize[3]; }
4717  else if((ptrgeom->p==FACE3)||(ptrgeom->p==CORN1)||(ptrgeom->p==CORN2) ){ kkn=0; kout=totalsize[3]; }
4718  else{
4719  dualfprintf(fail_file,"dir=%d no such location: %d\n",dir,ptrgeom->p);
4720  myexit(1);
4721  }
4722  if(
4723  ((startpos[3]+kk<=kkn)&&(BCtype[X3DN]==OUTFLOW)&&(pr[U1+dir-1] > 0.))
4724  ||((startpos[3]+kk>=kout)&&(BCtype[X3UP]==OUTFLOW)&&(pr[U1+dir-1] < 0.))
4725  ) {
4726  // set pre-primitive
4727  PALLLOOP(pl) pr0[pl]=pr[pl];
4728  pr[U3]=0;
4729 
4730  // account for changes
4731  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4732  int doingmhdfixup=1;
4733  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4734  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4735  }
4736  if(EOMRADTYPE!=EOMRADNONE&&(
4737  ((startpos[3]+kk<=kkn)&&(BCtype[X3DN]==OUTFLOW)&&(pr[URAD1+dir-1] > 0.))
4738  ||((startpos[3]+kk>=kout)&&(BCtype[X3UP]==OUTFLOW)&&(pr[URAD1+dir-1] < 0.))
4739  )
4740  ) {
4741  // set pre-primitive
4742  PALLLOOP(pl) pr0[pl]=pr[pl];
4743  pr[URAD3]=0;
4744 
4745  // account for changes
4746  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4747  int doingmhdfixup=1;
4748  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4749  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4750  }
4751  }
4752  else return(1); // uh
4753 
4754  return(0);
4755 }
4756 
4757 
4759 int inflow_check_3vel(int dir, FTYPE *pr, FTYPE *ucons, struct of_geom *ptrgeom, int finalstep)
4760 {
4761 
4762  return(inflow_check_4vel(dir,pr,ucons, ptrgeom,-1));
4763 
4764 }
4765 
4767 // GODMARK: check for correctness
4768 int inflow_check_rel4vel(int dir, FTYPE *pr, FTYPE *ucons, struct of_geom *ptrgeom, int finalstep)
4769 {
4770  FTYPE ucon[NDIM],uradcon[NDIM] ;
4771  FTYPE others[NUMOTHERSTATERESULTS];
4772  FTYPE othersrad[NUMOTHERSTATERESULTS];
4773  int ii,jj,kk,loc;
4774  int j,k ;
4775  int pl,pliter;
4776  FTYPE alpha,betacon,gamma,vsq ;
4777  FTYPE qsq;
4778  int iin,iout;
4779  int jjn,jout;
4780  int kkn,kout;
4781  int dofix=0, dofixrad=0;
4782  FTYPE pr0[NPR];
4783 
4784 
4785  // return(0);
4786  ii=ptrgeom->i;
4787  jj=ptrgeom->j;
4788  kk=ptrgeom->k;
4789  loc=ptrgeom->p;
4790 
4791 
4792  //ucon_calc(pr, ptrgeom, ucon,others) ;
4793 
4794  // PALLLOOP(pl) dualfprintf(fail_file,"nstep=%ld steppart=%d t=%21.15g :: pl=%d %21.15g\n",nstep,steppart,t,pl,pr[pl]);
4795 
4796  MYFUN(ucon_calc(pr, ptrgeom, ucon, others),"fixup.c:inflow_check_rel4vel()", "ucon_calc() dir=0", 1);
4797  MYFUN(ucon_calc(&pr[URAD1-U1], ptrgeom, uradcon, othersrad),"fixup.c:inflow_check_rel4vel()", "ucon_calc() dir=0", 1);
4798 
4799  // DLOOPA(pl) dualfprintf(fail_file,"ucon[%d]=%21.15g uconrad[%d]=%21.15g\n",pl,ucon[pl],pl,uradcon[pl]);
4800 
4801  dofix=dofixrad=0;
4802 
4803  if(dir==1){
4804  // for dir==1
4805  if((ptrgeom->p==CENT)||(ptrgeom->p==FACE2)||(ptrgeom->p==FACE3)||(ptrgeom->p==CORN1) ){ iin=-1; iout=totalsize[1]; }
4806  else if((ptrgeom->p==FACE1)||(ptrgeom->p==CORN2)||(ptrgeom->p==CORN3) ){ iin=0; iout=totalsize[1]; }
4807  else{
4808  dualfprintf(fail_file,"dir=%d no such location: %d\n",dir,ptrgeom->p);
4809  myexit(1);
4810  }
4811  if(
4812  ((startpos[1]+ii<=iin)&&((BCtype[X1DN]==OUTFLOW || BCtype[X1DN]==HORIZONOUTFLOW) || BCtype[X1DN]==OUTFLOWNOINFLOW)&&(ucon[dir] > 0.))
4813  ||((startpos[1]+ii>=iout)&&((BCtype[X1UP]==OUTFLOW || BCtype[X1UP]==HORIZONOUTFLOW) || BCtype[X1UP]==OUTFLOWNOINFLOW)&&(ucon[dir] < 0.))
4814  ) {
4815  dofix=1;
4816  }
4817  if(EOMRADTYPE!=EOMRADNONE&&(
4818  ((startpos[1]+ii<=iin)&&((BCtype[X1DN]==OUTFLOW || BCtype[X1DN]==HORIZONOUTFLOW) || BCtype[X1DN]==OUTFLOWNOINFLOW)&&(uradcon[dir] > 0.))
4819  ||((startpos[1]+ii>=iout)&&((BCtype[X1UP]==OUTFLOW || BCtype[X1UP]==HORIZONOUTFLOW) || BCtype[X1UP]==OUTFLOWNOINFLOW)&&(uradcon[dir] < 0.))
4820  )
4821  ) {
4822  dofixrad=1;
4823  }
4824  if(
4825  ((startpos[1]+ii<=iin)&&(BCtype[X1DN]==FIXEDOUTFLOW)&&(pr[U1+dir-1] > 0.))
4826  ||((startpos[1]+ii>=iout)&&(BCtype[X1UP]==FIXEDOUTFLOW)&&(pr[U1+dir-1] < 0.))
4827  ) {
4828  // set pre-primitive
4829  PALLLOOP(pl) pr0[pl]=pr[pl];
4830  // then inflow according to Bondi-like atmosphere
4831  // GODMARK: need to ensure this gives well-defined answers during init.c processing
4832  set_atmosphere(1,WHICHVEL,ptrgeom,pr); // can change all pr's
4833  dofix=0; // assume in boundary
4834  }
4835  }
4836  else if(dir==2){
4837  // for dir==2
4838  if((ptrgeom->p==CENT)||(ptrgeom->p==FACE1)||(ptrgeom->p==FACE3)||(ptrgeom->p==CORN2) ){ jjn=-1; jout=totalsize[2]; }
4839  else if((ptrgeom->p==FACE2)||(ptrgeom->p==CORN1)||(ptrgeom->p==CORN3) ){ jjn=0; jout=totalsize[2]; }
4840  else{
4841  dualfprintf(fail_file,"dir=%d no such location: %d\n",dir,ptrgeom->p);
4842  myexit(1);
4843  }
4844  if(
4845  ((startpos[2]+jj<=jjn)&&(BCtype[X2DN]==OUTFLOW || BCtype[X2DN]==OUTFLOWNOINFLOW)&&(ucon[dir] > 0.))
4846  ||((startpos[2]+jj>=jout)&&(BCtype[X2UP]==OUTFLOW || BCtype[X2UP]==OUTFLOWNOINFLOW)&&(ucon[dir] < 0.))
4847  ) {
4848  dofix=2;
4849  }
4850  if(EOMRADTYPE!=EOMRADNONE&&(
4851  ((startpos[2]+jj<=jjn)&&(BCtype[X2DN]==OUTFLOW || BCtype[X2DN]==OUTFLOWNOINFLOW)&&(uradcon[dir] > 0.))
4852  ||((startpos[2]+jj>=jout)&&(BCtype[X2UP]==OUTFLOW || BCtype[X2UP]==OUTFLOWNOINFLOW)&&(uradcon[dir] < 0.))
4853  )
4854  ) {
4855  dofixrad=2;
4856  }
4857  }
4858  else if(dir==3){
4859  // for dir==3
4860  if((ptrgeom->p==CENT)||(ptrgeom->p==FACE1)||(ptrgeom->p==FACE2)||(ptrgeom->p==CORN3) ){ kkn=-1; kout=totalsize[3]; }
4861  else if((ptrgeom->p==FACE3)||(ptrgeom->p==CORN1)||(ptrgeom->p==CORN2) ){ kkn=0; kout=totalsize[3]; }
4862  else{
4863  dualfprintf(fail_file,"dir=%d no such location: %d\n",dir,ptrgeom->p);
4864  myexit(1);
4865  }
4866  if(
4867  ((startpos[3]+kk<=kkn)&&(BCtype[X3DN]==OUTFLOW || BCtype[X3DN]==OUTFLOWNOINFLOW)&&(ucon[dir] > 0.))
4868  ||((startpos[3]+kk>=kout)&&(BCtype[X3UP]==OUTFLOW || BCtype[X3UP]==OUTFLOWNOINFLOW)&&(ucon[dir] < 0.))
4869  ) {
4870  dofix=3;
4871  }
4872  if(EOMRADTYPE!=EOMRADNONE&&(
4873  ((startpos[3]+kk<=kkn)&&(BCtype[X3DN]==OUTFLOW || BCtype[X3DN]==OUTFLOWNOINFLOW)&&(uradcon[dir] > 0.))
4874  ||((startpos[3]+kk>=kout)&&(BCtype[X3UP]==OUTFLOW || BCtype[X3UP]==OUTFLOWNOINFLOW)&&(uradcon[dir] < 0.))
4875  )
4876  ) {
4877  dofixrad=3;
4878  }
4879  }
4880  else{
4881  dualfprintf(fail_file,"Shouldn't reach dir=%d\n",dir);
4882  return(1); // uh
4883  }
4884 
4885 
4886 
4887  if(dofix){
4888  // set pre-primitive
4889  PALLLOOP(pl) pr0[pl]=pr[pl];
4890  FTYPE prdiag[NPR];
4891  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4892 
4893 
4894  /* find gamma and remove it from primitives */
4895  if(gamma_calc(pr,ptrgeom,&gamma,&qsq)>=1){
4896  dualfprintf(fail_file,"gamma calc failed: inflow_check_rel4vel\n");
4897  if (fail(ii,jj,kk,loc,FAIL_UTCALC_DISCR) >= 1)
4898  return (1);
4899  }
4900  pr[U1] /= gamma ;
4901  pr[U2] /= gamma ;
4902  pr[U3] /= gamma ;
4903  alpha = 1./sqrt(-ptrgeom->gcon[GIND(0,0)]) ;
4904 
4905  /* reset radial velocity so radial 4-velocity
4906  * is zero */
4907  if(dofix==1){
4908  betacon = ptrgeom->gcon[GIND(0,1)]*alpha*alpha ;
4909  pr[U1] = betacon/alpha ; // gives 3-vel contravariant
4910  }
4911  else if(dofix==2){
4912  betacon = ptrgeom->gcon[GIND(0,2)]*alpha*alpha ;
4913  pr[U2] = betacon/alpha ; // gives 3-vel contravariant
4914  }
4915  else if(dofix==3){
4916  betacon = ptrgeom->gcon[GIND(0,3)]*alpha*alpha ;
4917  pr[U3] = betacon/alpha ; // gives 3-vel contravariant
4918  }
4919  /* now find new gamma and put it back in */
4920  vsq = 0. ;
4921  SLOOP(j,k) vsq += ptrgeom->gcov[GIND(j,k)]*pr[U1+j-1]*pr[U1+k-1] ;
4922 
4923  if(vsq<0.0){
4924  if(vsq>-NUMEPSILON*100.0) vsq=0.0; // machine precision thing
4925  else if (fail(ii,jj,kk,loc,FAIL_VSQ_NEG) >= 1){
4926  trifprintf("vsq=%21.15g\n",vsq);
4927  return (1);
4928  }
4929  }
4930 
4931  // it's possible that setting ucon(bc comp)->0 leads to v>c, so just reduce gamma to GAMMAMAX if that's the case
4932  if(vsq>=1.0){
4933  if(debugfail>=1) dualfprintf(fail_file,"i=%d j=%d k=%d inflow limit required change in gamma (after dofix==%d): vsq=%21.15g newvsq=%21.15g\n",ii+startpos[1],jj+startpos[2],kk+startpos[3],dofix,vsq,1.0-1.0/(GAMMAMAX*GAMMAMAX));
4934 
4935  // new vsq
4936  vsq = 1.0-1.0/(GAMMAMAX*GAMMAMAX);
4937 
4938  }
4939 
4940  gamma = 1./sqrt(1. - vsq) ;
4941  pr[U1] *= gamma ;
4942  pr[U2] *= gamma ;
4943  pr[U3] *= gamma ;
4944 
4945  // only for boundary conditions, not active zones, hence -1.0 instead of finalstep
4946  int doingmhdfixup=1;
4947  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
4948  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
4949 
4950  }
4951 
4952 
4953 
4954  if(dofixrad){
4955 
4956  // set pre-primitive
4957  PALLLOOP(pl) pr0[pl]=pr[pl];
4958  FTYPE prdiag[NPR];
4959  PLOOP(pliter,pl) prdiag[pl]=pr0[pl];
4960 
4961 
4962  /* find gamma and remove it from primitives */
4963  if(gamma_calc(&pr[URAD1-U1],ptrgeom,&gamma,&qsq)>=1){
4964  dualfprintf(fail_file,"gamma calc failed: inflow_check_rel4vel\n");
4965  if (fail(ii,jj,kk,loc,FAIL_UTCALC_DISCR) >= 1)
4966  return (1);
4967  }
4968  pr[URAD1] /= gamma ;
4969  pr[URAD2] /= gamma ;
4970  pr[URAD3] /= gamma ;
4971  alpha = 1./sqrt(-ptrgeom->gcon[GIND(0,0)]) ;
4972 
4973  /* reset radial velocity so radial 4-velocity
4974  * is zero */
4975  if(dofixrad==1){
4976  betacon = ptrgeom->gcon[GIND(0,1)]*alpha*alpha ;
4977  pr[URAD1] = betacon/alpha ; // gives 3-vel contravariant
4978  }
4979  else if(dofixrad==2){
4980  betacon = ptrgeom->gcon[GIND(0,2)]*alpha*alpha ;
4981  pr[URAD2] = betacon/alpha ; // gives 3-vel contravariant
4982  }
4983  else if(dofixrad==3){
4984  betacon = ptrgeom->gcon[GIND(0,3)]*alpha*alpha ;
4985  pr[URAD3] = betacon/alpha ; // gives 3-vel contravariant
4986  }
4987  /* now find new gamma and put it back in */
4988  vsq = 0. ;
4989  SLOOP(j,k) vsq += ptrgeom->gcov[GIND(j,k)]*pr[URAD1+j-1]*pr[URAD1+k-1] ;
4990 
4991  if(vsq<0.0){
4992  if(vsq>-NUMEPSILON*100.0) vsq=0.0; // machine precision thing
4993  else if (fail(ii,jj,kk,loc,FAIL_VSQ_NEG) >= 1){
4994  trifprintf("vsq=%21.15g\n",vsq);
4995  return (1);
4996  }
4997  }
4998 
4999  // it's possible that setting ucon(bc comp)->0 leads to v>c, so just reduce gamma to GAMMAMAX if that's the case
5000  if(vsq>=1.0){
5001  if(debugfail>=1) dualfprintf(fail_file,"i=%d j=%d k=%d inflow limit required change in gamma (after dofix==%d): vsq=%21.15g newvsq=%21.15g\n",ii+startpos[1],jj+startpos[2],kk+startpos[3],dofix,vsq,1.0-1.0/(GAMMAMAX*GAMMAMAX));
5002 
5003  // new vsq
5004  vsq = 1.0-1.0/(GAMMAMAX*GAMMAMAX);
5005 
5006  }
5007 
5008  gamma = 1./sqrt(1. - vsq) ;
5009  pr[URAD1] *= gamma ;
5010  pr[URAD2] *= gamma ;
5011  pr[URAD3] *= gamma ;
5012 
5013  // only for boundary conditions, not active zones, hence -1.0 instead of finalstep
5014  int doingmhdfixup=1;
5015  diag_fixup((DOENOFLUX != NOENOFLUX),prdiag, pr, ucons, ptrgeom, finalstep,doingmhdfixup,COUNTINFLOWACT);
5016  PLOOP(pliter,pl) prdiag[pl]=pr[pl];
5017 
5018  }
5019 
5020 
5021  if(dofix||dofixrad){
5022  return(-1);
5023  }
5024 
5025  return(0);
5026 
5027 }
5028 
5029 
5030 // fixup fluxes
5033 void fix_flux(FTYPE (*pb)[NSTORE2][NSTORE3][NPR],FTYPE (*F1)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*F2)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*F3)[NSTORE2][NSTORE3][NPR+NSPECIAL])
5034 {
5035  int i,j,k,pl ;
5036  FTYPE sth ;
5037  FTYPE X[NDIM],V[NDIM],r,th ;
5038  int inboundloop[NDIM];
5039  int outboundloop[NDIM];
5040  int innormalloop[NDIM];
5041  int outnormalloop[NDIM];
5043  int riin,riout,rjin,rjout,rkin,rkout;
5044  int dosetbc[COMPDIM*2];
5045  int ri;
5046  int boundvartype=BOUNDFLUXTYPE;
5047 
5049  //
5050  // set bound loop
5051  //
5053  set_boundloop(boundvartype, inboundloop,outboundloop,innormalloop,outnormalloop,inoutlohi, &riin, &riout, &rjin, &rjout, &rkin, &rkout, dosetbc);
5054  //enerregion=ACTIVEREGION; // now replaces TRUEGLOBALENERREGION
5055  // localenerpos=enerposreg[enerregion];
5056 
5057 
5058  // this has nothing to deal with MPI-boundaries, so ok as is
5059  // only applies for polar axis
5060  if(mycpupos[2]==0){
5061  if(BCtype[X2DN]==POLARAXIS){
5062  LOOPX2dir{
5063  // emf should be antisymmetric around polar axes? // GODMARK: how does this mix with metric?
5064  LOOPBOUND2IN{
5065  MACP0A1(F1,i,j,k,B1) = 0;
5066  MACP0A1(F1,i,j,k,B2) = -MACP0A1(F1,i,-(jp1mac(j)),k,B2) ; // symmetric positions around polar axis, but antisymmetric value
5067  MACP0A1(F3,i,j,k,B2) = -MACP0A1(F3,i,-(jp1mac(j)),k,B2) ; // symmetric positions around polar axis, but antisymmetric value
5068  MACP0A1(F3,i,j,k,B3) = 0;
5069  }
5070  // all should be 0 except kinetic energy flux
5071  // GODMARK: I'm unsure if emf is not unlike, say, \Omega, which is a well-defined thing on the axis.
5072  PALLLOOP(pl) if(pl!=U2) MACP0A1(F2,i,0,k,pl) = 0. ;
5073  }
5074  }
5075  }
5076  if(mycpupos[2]==ncpux2-1){
5077  if(BCtype[X2UP]==POLARAXIS){
5078  LOOPX2dir{
5079  // emf
5080  LOOPBOUND2OUT{
5081  MACP0A1(F1,i,j,k,B2) = -MACP0A1(F1,i,jrefshiftmac(j),k,B2) ;
5082  MACP0A1(F3,i,j,k,B2) = -MACP0A1(F3,i,jrefshiftmac(j),k,B2) ;
5083  }
5084  // GODMARK: unsure
5085  PALLLOOP(pl) if(pl!=U2) MACP0A1(F2,i,N2,k,pl) = 0. ;
5086  }
5087  }
5088  }
5089 
5090  // avoid mass flux in wrong direction, so consistent with velocity fix
5091  // how to treat other fluxes?
5092  if(mycpupos[1]==0){
5093  if((BCtype[X1DN]==OUTFLOW || BCtype[X1DN]==HORIZONOUTFLOW)){
5094  LOOPX1dir{
5095  ri=riin;
5096  LOOPBOUND1IN{
5097  if(MACP0A1(F1,i,j,k,RHO)>0) MACP0A1(F1,i,j,k,RHO)=0;
5098  }
5099  }
5100  }
5101  }
5102  if(mycpupos[1]==ncpux1-1){
5103  if((BCtype[X1UP]==OUTFLOW || BCtype[X1UP]==HORIZONOUTFLOW)){
5104  LOOPX1dir{
5105  LOOPBOUND1OUT{
5106  if(MACP0A1(F1,i,j,k,RHO)<0) MACP0A1(F1,i,j,k,RHO)=0;
5107  }
5108  }
5109  }
5110  }
5111 
5112 }
5113 
5114 
5116 void diag_eosfaillookup(int i, int j, int k)
5117 {
5118  int whocalled = COUNTEOSLOOKUPFAIL;
5119  int tscale;
5120 
5121  // count every time corrects
5122  if(DODEBUG){
5123  if(i==AVOIDI && j==AVOIDJ && k==AVOIDK){
5124  // then do nothing since don't know where failure occurred
5125  }
5126  else if(i<-N1BND || i>N1-1+N1BND ||j<-N2BND || j>N2-1+N2BND ||k<-N3BND || k>N3-1+N3BND ){
5127  dualfprintf(fail_file,"In diag_eosfaillookup() whocalled=%d for i=%d j=%d k=%d\n",whocalled,i,j,k);
5128  myexit(3472762356);
5129  }
5130  int indexfinalstep;
5131  FINALSTEPLOOP(indexfinalstep) TSCALELOOP(tscale) GLOBALMACP0A3(failfloorcount,i,j,k,indexfinalstep,tscale,whocalled)++;
5132  }
5133 }