HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
utoprimgen.c
Go to the documentation of this file.
1 
7 #include "decs.h"
8 
9 
10 // NOTEMARK: if using primtoU() or primtoflux(), these respect nprlist for PLOOP, hence why these tests use PLOOP while others use PALLLOOP
11 
12 
13 
15 #if(PRODUCTION>=2)
16 #define CHECKONINVFRAC (1E-1)
17 #elif(PRODUCTION==1)
18 #define CHECKONINVFRAC (1E-2)
19 #else
20 #define CHECKONINVFRAC (MAX(1E-7,newtonstats->tryconv*1E3)) // can't check if didn't ask for large error.
21 #endif
22 
24 #define FAILIFBADCHECK 1
25 
27 #define CHECKONINVFRACFAIL (1E-1)
28 
29 #define REPORTCYCLE (10)
30 
32 #define ENTROPYFIXGUESSEXTERNAL (ENTROPYFIXGUESS)
33 
34 
35 
36 
37 static int negdensitycheck(int finalstep, FTYPE *prim, PFTYPE *pflag);
38 static int check_on_inversion(int checkoninversiongas, int checkoninversionrad, int usedhotinversion,int usedentropyinversion,int usedcoldinversion,int usedffdeinversion, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_geom *ptrgeom, FTYPE *Uold, FTYPE *Unew, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
39 static int debug_utoprimgen(PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, struct of_geom *ptrgeom, FTYPE *Uold, FTYPE *Unew);
40 static int compare_ffde_inversions(int showmessages, int allowlocalfailurefixandnoreport, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_geom *ptrgeom, FTYPE *Ugeomfree0, FTYPE*Ugeomfree, FTYPE *Uold, FTYPE *Unew, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
41 
42 static int tryhotinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
43 static int tryentropyinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
44 static int trycoldinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
45 static int tryffdeinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
46 
47 
48 
49 
50 
51 
53 int Utoprimgen(int showmessages, int checkoninversiongas, int checkoninversionrad, int allowlocalfailurefixandnoreport, int finalstep, int *eomtype, int whichcap, int whichmethod, int modprim, int evolvetype, int inputtype,FTYPE *U, struct of_state *qptr, struct of_geom *ptrgeom, FTYPE dissmeasure, FTYPE *pi, FTYPE *pr, struct of_newtonstats *newtonstats)
54 {
55  // debug
56  int i, j, k;
57  FTYPE Ugeomfree[NPR],Ugeomfree0[NPR];
58  FTYPE pr0[NPR];
59  FTYPE prother[NPR];
60  int whichentropy;
61  // struct of_state q;
62  FTYPE Uold[NPR],Unew[NPR];
63  int otherfail;
64  extern void UtoU(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
65  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
66  int Utoprimgen_compare(int showmessages, int allowlocalfailurefixandnoreport, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
67  int Utoprimgen_tryagain(int showmessages, int allowlocalfailurefixandnoreport, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE *Ugeomfree,struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
68  int Utoprimgen_tryagain2(int showmessages, int allowlocalfailurefixandnoreport, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE *Ugeomfree,struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
69  void convert_U_removerestmassfromuu(int utoprimverison, int removerestmassfromuu, FTYPE *U);
70  int invert_scalars1(struct of_geom *ptrgeom, FTYPE *Ugeomfree,FTYPE *pr);
71  int invert_scalars2(struct of_geom *ptrgeom, FTYPE *Ugeomfree, struct of_state *q, FTYPE *pr);
72  int pl,pliter;
73  PFTYPE lpflag,lpflagrad;
74  int usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion;
75  FTYPE pressuremem=-1.0;
76  FTYPE *pressure=&pressuremem;
77  int eomtypelocal;
78 
79 
80 
82  //
83  // set check flag to default if user didn't want to choose
84  //
86  if(checkoninversiongas==CHECKONINVERSIONDEFAULT) checkoninversiongas=CHECKONINVERSION;
87  if(checkoninversionrad==CHECKONINVERSIONDEFAULT) checkoninversionrad=CHECKONINVERSIONRAD;
88 
89 
90 
91 
92  // DEBUG:
93  // dualfprintf(fail_file,"Doing inversion for ijk=%d %d %d nstep=%ld steppart=%d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
94 
95 
96 
97 
98 
100  //
101  // INVERT Magnetic field or restore magnetic field for SPLITNPR case
102  //
104 
105 #if(SPLITNPR)
106  if(nprlist[nprstart]==B1 && nprlist[nprend]==B3){ // then assume doing B1,B2,B3
107  // invert magnetic field only
108  PLOOPBONLY(pl) pr[pl]=U[pl]/ptrgeom->e[pl]; // direct inversion from geometry-free conserved quantity
109  return(0);
110  }
111  else{
112  // otherwise assume want to invert ONLY non-B components and assume using same memory space
113  // can achieve this by setting Ugeomfree to *existing* pr (assume memory space for SPLITNPR step 0 and 1 didn't change
114  // overwrites update (that is no field update done on second pass) to magnetic field
115  // Note that field U not updated in this pass, so need to fill with something.
116  // Assume pr here is pbb that contains field-update's Bnew
117  PLOOPBONLY(pl) U[pl]=pr[pl]*ptrgeom->e[pl];
118  }
119 #else
120  // invert magnetic field
121  // direct inversion from geometry-free conserved quantity
122  // assume normal inversion takes care of this
123  // PLOOPBONLY(pl) pr[pl]=U[pl]/ptrgeom->e[pl];
124 #endif
125 
126 
127 
128 
129 
130 
131 
132 
133 
135  //
136  // Notice that reconstruct "standard" geometry-free conserved quantities by first modifying the geometry prefactor and THEN dealing with rest-mass or other subtractions and additions.
137  // This is consistent with primtoflux() and how primtoflux() is used in source_conn().
138  //
140  UtoU(inputtype,UNOTHING,ptrgeom,U,Ugeomfree);
141  // e.g. if REMOVERESTMASSFROMUU==1 and inputtype==UEVOLVE, then Ugeomfree has energy T^t_t that includes rest-mass
142 #if(SPLITNPR)
143  if(!(nprlist[nprstart]==B1 && nprlist[nprend]==B3)){
144  // then need to update field quantities since UtoU uses PLOOP not PALLLOOP -- GODMARK: could use PALLLOOP in UtoU, but then adds excessive code to phys.c related to SPLITNPR
145  PLOOPBONLY(pl) Ugeomfree[pl]=U[pl]/ptrgeom->e[pl];
146  }
147 #endif
148 
149 
150 
152  //
153  // Copy over Ugeomfree/pr to Ugeomfree0/pr0
154  //
156  PALLLOOP(pl){
157  Uold[pl]=Ugeomfree0[pl]=Ugeomfree[pl];
158  pr0[pl]=pr[pl];
159  }
160 
161 
162 
163 
164 
165 
167  //
168  // convert U into form appropriate for inversion routine
169  //
171  convert_U_removerestmassfromuu(UTOPRIMVERSION,REMOVERESTMASSFROMUU,Ugeomfree);
172  convert_U_removerestmassfromuu(UTOPRIMVERSION,REMOVERESTMASSFROMUU,Ugeomfree0);
173 
174 
175 
176 
178  //
179  // Setup which eomtype to use depending upon how got to this function
180  //
182  FTYPE fracenergy;
184  //
185  // if(nstep==4 && steppart==0){
186  // PLOOP(pliter,pl) dualfprintf(fail_file,"PRIMUTOPRIMGEN0(%d): pl=%d pp=%21.15g uu=%21.15g\n",*eomtype,pl,pr[pl],Ugeomfree[pl]);
187  // }
188 
189  static long long int didnothing=0,didsomething=0,didentropy=0,didenergy=0,didcold=0;
191  if(EOMDONOTHING(*eomtype)){
192 
193 
194  // if finalstep==0, then don't do inversion. If finalstep==1, only need to do inversion if ucum is different than final uf.
195  // then do nothing since assume already pr=pr[U].
196  // also don't change any failure flags, assuming prior flags are correct.
197 
198  // still can check inversion
199  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)<=UTOPRIMNOFAIL){
200  usedhotinversion=usedentropyinversion=usedcoldinversion=usedffdeinversion=0;
201  if(*eomtype==EOMDIDGRMHD) usedhotinversion=1;
202  if(*eomtype==EOMDIDENTROPYGRMHD) usedentropyinversion=1;
203  if(*eomtype==EOMDIDCOLDGRMHD) usedcoldinversion=1;
204  if(*eomtype==EOMDIDFFDE) usedffdeinversion=1;
205 
206  // check cold inversion if inversion thinks it was successful
207  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
208  }
209  if(DOEVOLVERHO){
210  negdensitycheck(finalstep, pr, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL));
211  }
212  didnothing++;
213  if(debugfail>=2) if(didnothing%(totalzones*REPORTCYCLE)==0) dualfprintf(fail_file,"DIDNOTHING: %lld : %ld %d : %d\n",didnothing,nstep,steppart,*eomtype);
214  return(0);
215  }
216  else{
217  // setup default eomtype
218  if(*eomtype==EOMDEFAULT) eomtypelocal=EOMTYPE; // use default
219  // if did certain inversion on last sub-step, then assume want same inversion type (e.g. for finalstep==1 for TIMEORDER>2 cases)
220  else if(*eomtype==EOMDIDGRMHD) eomtypelocal=EOMGRMHD;
221  else if(*eomtype==EOMDIDENTROPYGRMHD) eomtypelocal=EOMENTROPYGRMHD;
222  else if(*eomtype==EOMDIDCOLDGRMHD) eomtypelocal=EOMCOLDGRMHD;
223  else if(*eomtype==EOMDIDFFDE) eomtypelocal=EOMFFDE;
224  else if(*eomtype==EOMDIDFFDE2) eomtypelocal=EOMFFDE2;
225  else eomtypelocal=*eomtype; // force eomtype
226 
227  if(whichmethod==MODEPICKBEST){
228  set_fracenergy(ptrgeom->i,ptrgeom->j,ptrgeom->k,dissmeasure, &fracenergy);
229  }
230  else fracenergy = (eomtypelocal==EOMGRMHD ? 1.0 : 0.0);
231 
232  if(fracenergy<=0.0 && eomtypelocal==EOMGRMHD) eomtypelocal=EOMENTROPYGRMHD; // start with entropy
233  if(fracenergy>0.0 && eomtypelocal==EOMENTROPYGRMHD) eomtypelocal=EOMGRMHD; // start with hot
234 
235  if(eomtypelocal==EOMGRMHD) didenergy++;
236  if(eomtypelocal==EOMENTROPYGRMHD) didentropy++;
237  if(eomtypelocal==EOMCOLDGRMHD) didcold++;
238 
239  didsomething++;
240  if(debugfail>=2) if(didsomething%(totalzones*REPORTCYCLE)==0) dualfprintf(fail_file,"DIDSOMETHING: %lld : %ld %d : eomtype=%d -> eomtypelocal=%d : dids: %lld %lld %lld\n",didsomething,nstep,steppart,*eomtype,eomtypelocal,didenergy,didentropy,didcold);
241  }
242 
243 
244 
245 
246 
247 
248 
249 
250 
251 
252 
253 
254 
255 
256 
258  //
259  // START INVERSION PROCESS
260  //
261  //
263 
264 
265 
266 
267 
268 
269 
270 
271 
272 
274  //
275  // backup (in inversion routine format with already-inverted scalars)
276  //
278  PALLLOOP(pl){
279  Uold[pl]=Ugeomfree0[pl]=Ugeomfree[pl];
280  pr0[pl]=pr[pl];
281  }
282 
283 
284 
285 
286 
287 
288 
289 
291  //
292  // DO non-scalar INVERSION (from here after, only modify RHO,UU,U1,U2,U3,B1,B2,B3. Any initial guess should be using pr0 that contains other interpolated quantities.)
293  //
295 
296  // defaults
297  usedhotinversion=0;
298  usedentropyinversion=0;
299  usedcoldinversion=0;
300  usedffdeinversion=0;
301 
302 
303  // if some process already set fail flag (e.g. inversions somewhere else that wasn't reset) (e.g. like in phys.tools.rad.c for implicit or explicit solvers with radiation), then assume want to treat as failure for purposes of fixing up. That is, get inversion, but that inversion will be for undefined 4-force and only used in worst-case scenario for fixups.
304  PFTYPE preexistingfailgas=0;
305  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)>UTOPRIMNOFAIL) preexistingfailgas=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
306 
307  // Also see if radiation inversion got locally corrected. Then, might still do better to do multi-point averaging in fixups like with MHD variables. So capture this flag for fixups.
308  PFTYPE preexistingfailrad=0;
309  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)>UTOPRIMRADNOFAIL) preexistingfailrad=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
310 
311 
312 
313 
314 
315  int entropytried=0,hottried=0,coldtried=0,ffdetried=0;
316  PFTYPE entropypflag=UTOPRIMFAILGENERIC,hotpflag=UTOPRIMFAILGENERIC,coldpflag=UTOPRIMFAILGENERIC,ffdepflag=UTOPRIMFAILGENERIC;
317  PFTYPE entropyradinvmod=1,hotradinvmod=1,coldradinvmod=1,ffderadinvmod=1;
318  int entropyhardfailure=1,hothardfailure=1,coldhardfailure=1,ffdehardfailure=1;
319  FTYPE entropypr[NPR],hotpr[NPR],coldpr[NPR],ffdepr[NPR];
320 
321 
322 
323 
324 
325 
326  if(eomtypelocal==EOMGRMHD){
327 
328 
330  //
332  //
334 
335  // report back that used this
336  *eomtype=eomtypelocal;
337 
339  // If just using pr/pr0 for guess, then fixup
341  if(ENTROPYFIXGUESSEXTERNAL && modprim==1){
342  // qptr is not final qptr, just previous from "pi" or at best "pb"
343  entropyfixguess(qptr, ptrgeom, Ugeomfree, pr);
344  // also get highest out of current "flux" and "initial" step parts.
345  pr[UU]=MAX(fabs(pr[UU]),fabs(pi[UU]));
346  }
347 
348 
349  // Inversion call
350  hottried=1;
351  if(UTOPRIMVERSION!=UTOPRIMCOMPARE) Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMVERSION, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
352  else Utoprimgen_compare(showmessages, allowlocalfailurefixandnoreport, eomtypelocal, whichcap, EVOLVENOENTROPY,Ugeomfree,ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
353 
354 
355  // try other methods (assumes all methods can handle WHICHVEL, etc. used for primary model)
356  // right now, all can handle WHICHVEL==VELREL4 and energy equation evolution and REMOVERESTMASSFROMUU=0,1
357 #if((WHICHVEL==VELREL4)&&(REMOVERESTMASSFROMUU<=1)&&(UTOPRIMTRYAGAIN))
358  Utoprimgen_tryagain(showmessages, allowlocalfailurefixandnoreport, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree0, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
359 #elif((WHICHVEL==VELREL4)&&(REMOVERESTMASSFROMUU==2)&&(UTOPRIMTRYAGAIN))
360  // Can only try again using same type of U since tryagain code doesn't convert U
361  Utoprimgen_tryagain2(showmessages, allowlocalfailurefixandnoreport, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree0, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
362 #endif
363  PLOOP(pliter,pl) hotpr[pl]=pr[pl]; // save hotpr
364 
365 
366  // get failure flag
367  hotpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
368  hotradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
369  hothardfailure=(IFUTOPRIMFAIL(hotpflag) && IFUTOPRIMFAILSOFT(hotpflag)==0);
370 
371  if(!hothardfailure){
372  // report back that used this
373  *eomtype=EOMGRMHD;
374 
375  usedhotinversion=1;
376  usedentropyinversion=0;
377  usedcoldinversion=0;
378  usedffdeinversion=0;
379  // check on hot inversion if it thinks it was successful
380  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
381 
382  // adjust failure flag if check on inversion found issue
383  hotpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
384  hotradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
385  hothardfailure=(IFUTOPRIMFAIL(hotpflag) && IFUTOPRIMFAILSOFT(hotpflag)==0);
386 
387  }
388 
389 
390  // normally don't ever do this unless really debugging inversion.
391  if(0&&debugfail>=2&&hothardfailure){ // DEBUG: only report if hard failure. Seems when gets negative density or internal energy, jon's inversion is fine.
392  // first report info so can check on inversion
393  extern int mathematica_report_check(int radinvmod, int failtype, long long int failnum, int gotfirstnofail, int eomtypelocal, int itermode, FTYPE errorabs, FTYPE errorabsbestexternal, int iters, int iterstotal, FTYPE realdt,struct of_geom *ptrgeom, FTYPE *ppfirst, FTYPE *pp, FTYPE *pb, FTYPE *piin, FTYPE *prtestUiin, FTYPE *prtestUU0, FTYPE *uu0, FTYPE *uu, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, struct of_state *q, FTYPE *dUother);
394  static long long int failnum=0;
395  FTYPE fakedt=0.0; // since no 4-force
396  FTYPE fakeCUf[NUMDTCUFS]={0}; // fake
397  FTYPE dUother[NPR]={0};// fake
398  // struct of_state *qptr=NULL; // fake
399  failnum++;
400  // fake ppfirst as pr
401  mathematica_report_check(0, 2, failnum, (int)hotpflag, eomtypelocal, 0, 0.0, 0.0, -1, -1, fakedt, ptrgeom, pr, pr, pr, pr0, pr0, pr0, Ugeomfree0, Ugeomfree, Ugeomfree0, Ugeomfree0, fakeCUf, qptr, dUother);
402  }
403 
404 
406  // If hot GRMHD failed or gets suspicious solution, revert to entropy GRMHD if solution
407  // If radiation, then this redoes radiation inversion since entropy would give new velocity and local corrections in u2p_rad() might use velocity.
409  // int forcetryentropy=(whichmethod==MODEPICKBEST && fracenergy!=1.0 || hotpflag>0 && whichmethod==MODEPICKBEST && fracenergy!=1.0);
410  int forcetryentropy=0; // force
411  // if(HOT2ENTROPY && (hotpflag>0 && whichmethod==MODEPICKREVERT || forcetryentropy)){
412  if(HOT2ENTROPY && HOTANYFAIL(hotpflag)){
413 
414  entropytried=tryentropyinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, hotpflag, forcetryentropy, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
415  PLOOP(pliter,pl) entropypr[pl]=pr[pl]; // save entropypr
416  if(entropytried){
417 
418  // get failure flag
419  entropypflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
420  entropyradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
421  entropyhardfailure=(IFUTOPRIMFAIL(entropypflag) && IFUTOPRIMFAILSOFT(entropypflag)==0);
422 
423  if(!entropyhardfailure){
424  // report back that used this
425  *eomtype=EOMENTROPYGRMHD;
426 
427  usedhotinversion=0;
428  usedentropyinversion=1;
429  usedcoldinversion=0;
430  usedffdeinversion=0;
431 
432  // check entropy inversion if inversion thinks it was successful
433  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
434 
435  // adjust failure flag
436  entropypflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
437  entropyradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
438  entropyhardfailure=(IFUTOPRIMFAIL(entropypflag) && IFUTOPRIMFAILSOFT(entropypflag)==0);
439  }
440  }
441 
442  }
443  else entropypflag=1;
444 
445 
446 
448  // If hot GRMHD failed or gets suspicious solution, revert to cold GRMHD if solution is cold
450  if(HOT2COLD && (ENTROPYANYFAIL(entropypflag) && HOTANYFAIL(hotpflag)) ){
451 
452  coldtried=trycoldinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, hotpflag, 0, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
453  PLOOP(pliter,pl) coldpr[pl]=pr[pl]; // save coldpr
454  if(coldtried){
455 
456  // get failure flag
457  coldpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
458  coldradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
459  coldhardfailure=(IFUTOPRIMFAIL(coldpflag) && IFUTOPRIMFAILSOFT(coldpflag)==0);
460 
461  if(!coldhardfailure){
462  usedhotinversion=0;
463  usedentropyinversion=0;
464  usedcoldinversion=1;
465  usedffdeinversion=0;
466 
467  // report back that used this
468  *eomtype=EOMCOLDGRMHD;
469 
470  // check cold inversion if inversion thinks it was successful
471  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
472 
473  // adjust failure flag
474  coldpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
475  coldradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
476  coldhardfailure=(IFUTOPRIMFAIL(coldpflag) && IFUTOPRIMFAILSOFT(coldpflag)==0);
477  }
478  }
479 
480  }
481  else coldpflag=1;
482 
483 
485  // If hot GRMHD failed or gets suspicious solution, revert to FFDE GRMHD if solution is FFDE
487  if(HOT2FFDE && (COLDANYFAIL(coldpflag) && ENTROPYANYFAIL(entropypflag) && HOTANYFAIL(hotpflag)) ){
488 
489  ffdetried=tryffdeinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, hotpflag, 0, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
490  PLOOP(pliter,pl) ffdepr[pl]=pr[pl]; // save ffdepr
491  if(ffdetried){
492 
493  // get failure flag
494  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
495  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
496  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
497 
498  if(!ffdehardfailure){
499  usedhotinversion=0;
500  usedentropyinversion=0;
501  usedcoldinversion=0;
502  usedffdeinversion=1;
503 
504  // report back that used this
505  *eomtype=EOMFFDE;
506 
507  // check ffde inversion if inversion thinks it was successful
508  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
509 
510  // adjust failure flag
511  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
512  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
513  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
514  }
515  }
516 
517  }
518  else ffdepflag=1;
519 
520 
521 
522 
523  }
524  else if(eomtypelocal==EOMENTROPYGRMHD){
526  //
528  //
529  // direct entropy evolution (can use old Utoprim() or new code, but not all codes have entropy inversion)
530  //
532 
533  // report back that used this
534  *eomtype=eomtypelocal;
535 
537  // If just using pr/pr0 for guess, then fixup
539  if(ENTROPYFIXGUESSEXTERNAL && modprim==1){
540  // qptr is not final qptr, just previous from "pi" or at best "pb"
541  entropyfixguess(qptr, ptrgeom, Ugeomfree, pr);
542  // also get highest out of current "flux" and "initial" step parts.
543  pr[UU]=MAX(fabs(pr[UU]),fabs(pi[UU]));
544  }
545 
546 
547  // INVERSION
548  entropytried=1;
549  // setup as if full entropy evolution
550  whichentropy=EVOLVEFULLENTROPY;
551  // get entropy evolution inversion
552  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtypelocal, whichcap, whichentropy, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
553  PLOOP(pliter,pl) entropypr[pl]=pr[pl]; // save entropypr
554 
555  // get failure flag
556  entropypflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
557  entropyradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
558  entropyhardfailure=(IFUTOPRIMFAIL(entropypflag) && IFUTOPRIMFAILSOFT(entropypflag)==0);
559 
560  if(!entropyhardfailure){
561 
562  // report back that used this
563  *eomtype=EOMENTROPYGRMHD;
564 
565  usedhotinversion=0;
566  usedentropyinversion=1;
567  usedcoldinversion=0;
568  usedffdeinversion=0;
569  // check entropy inversion
570  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
571 
572  // adjust failure flag
573  entropypflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
574  entropyradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
575  entropyhardfailure=(IFUTOPRIMFAIL(entropypflag) && IFUTOPRIMFAILSOFT(entropypflag)==0);
576  }
577 
578 
579 
581  // If entropy GRMHD failed or gets suspicious solution, revert to hot GRMHD
583  // if(ENTROPY2HOT && (entropypflag>0 && whichmethod==MODEPICKREVERT || (whichmethod==MODEPICKBEST))){
584  // below is consistent with hot entropy forced when fracenergy=0.0 as long as entropy didn't fail to invert.
585  // int forcetryhot = (whichmethod==MODEPICKBEST)&&(entropypflag>0&&fracenergy==0.0 || fracenergy!=0.0);
586  // override since not using fracenergy approach and above seems wrong
587  int forcetryhot=0;
588  // if(ENTROPY2HOT && (entropypflag>0 && whichmethod==MODEPICKREVERT || forcetryhot)){
589  if(ENTROPY2HOT && ENTROPYANYFAIL(entropypflag)){
590 
591  hottried=tryhotinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, entropypflag, forcetryhot, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
592  PLOOP(pliter,pl) hotpr[pl]=pr[pl]; // save hotpr
593  if(hottried){
594 
595  // get failure flag
596  hotpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
597  hotradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
598  hothardfailure=(IFUTOPRIMFAIL(hotpflag) && IFUTOPRIMFAILSOFT(hotpflag)==0);
599 
600  if(!hothardfailure){
601 
602  // report back that used this
603  *eomtype=EOMGRMHD;
604 
605  // check on hot inversion if it thinks it was successful
606  usedhotinversion=1;
607  usedentropyinversion=0;
608  usedcoldinversion=0;
609  usedffdeinversion=0;
610  // check on hot inversion
611  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
612 
613  // adjust failure flag
614  hotpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
615  hotradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
616  hothardfailure=(IFUTOPRIMFAIL(hotpflag) && IFUTOPRIMFAILSOFT(hotpflag)==0);
617  }
618  }
619 
620  }
621  else hotpflag=1;
622 
623 
625  // If entropy GRMHD failed or gets suspicious solution, revert to cold GRMHD if solution is cold
626  // This is the same trycoldinversion() as for HOT2COLD
628  if(ENTROPY2COLD && (ENTROPYANYFAIL(entropypflag) && HOTANYFAIL(hotpflag)) ){
629  coldtried=trycoldinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, entropypflag, 0, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
630  PLOOP(pliter,pl) coldpr[pl]=pr[pl]; // save coldpr
631 
632  if(coldtried){
633 
634  // get failure flag
635  coldpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
636  coldradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
637  coldhardfailure=(IFUTOPRIMFAIL(coldpflag) && IFUTOPRIMFAILSOFT(coldpflag)==0);
638 
639  if(!coldhardfailure){
640  // report back that used this
641  *eomtype=EOMCOLDGRMHD;
642 
643  usedhotinversion=0;
644  usedentropyinversion=0;
645  usedcoldinversion=1;
646  usedffdeinversion=0;
647 
648  // check cold inversion
649  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
650 
651  // adjust failure
652  coldpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
653  coldradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
654  coldhardfailure=(IFUTOPRIMFAIL(coldpflag) && IFUTOPRIMFAILSOFT(coldpflag)==0);
655  }
656  }
657  }
658  else coldpflag=1;
659 
660 
662  // If entropy GRMHD failed or gets suspicious solution, revert to FFDE GRMHD if solution is FFDE
664  if(ENTROPY2FFDE && (COLDANYFAIL(coldpflag) && ENTROPYANYFAIL(entropypflag) && HOTANYFAIL(hotpflag)) ){
665 
666  ffdetried=tryffdeinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, entropypflag, 0, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
667  PLOOP(pliter,pl) ffdepr[pl]=pr[pl]; // save ffdepr
668 
669  if(ffdetried){
670 
671  // get failure flag
672  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
673  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
674  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
675 
676  if(!ffdehardfailure){
677  usedhotinversion=0;
678  usedentropyinversion=0;
679  usedcoldinversion=0;
680  usedffdeinversion=1;
681 
682  // report back that used this
683  *eomtype=EOMFFDE;
684 
685  // check ffde inversion if inversion thinks it was successful
686  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
687 
688  // adjust failure flag
689  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
690  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
691  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
692  }
693  }
694  }
695  else ffdepflag=1;
696 
697 
698 
699  }
700  else if(eomtypelocal==EOMCOLDGRMHD){
702  //
704  //
706 
707  // report back that used this
708  *eomtype=eomtypelocal;
709 
710 
711  if(1){
712  // Jon's inversion
713  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
714  }
715  else if(0){ // not working yet
716  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMCOLDGRMHD, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
717  }
718  PLOOP(pliter,pl) coldpr[pl]=pr[pl]; // save coldpr
719 
720  coldpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
721  coldradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
722  coldhardfailure=(IFUTOPRIMFAIL(coldpflag) && IFUTOPRIMFAILSOFT(coldpflag)==0);
723 
724  if(!coldhardfailure){
725 
726  usedhotinversion=0;
727  usedentropyinversion=0;
728  usedcoldinversion=1;
729  usedffdeinversion=0;
730 
731  // check cold inversion
732  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
733 
734  // adjust failure
735  coldpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
736  coldradinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
737  coldhardfailure=(IFUTOPRIMFAIL(coldpflag) && IFUTOPRIMFAILSOFT(coldpflag)==0);
738  }
739 
740 
741 
743  // If cold GRMHD failed or gets suspicious solution, revert to FFDE GRMHD if solution is FFDE
745  if(ENTROPY2FFDE && (COLDANYFAIL(coldpflag)) ){
746 
747  ffdetried=tryffdeinversion(showmessages, allowlocalfailurefixandnoreport,finalstep, coldpflag, 0, whichcap, modprim, pi, pr0, pr, pressure, Ugeomfree, Ugeomfree0, qptr, ptrgeom,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
748  PLOOP(pliter,pl) ffdepr[pl]=pr[pl]; // save ffdepr
749 
750  if(ffdetried){
751 
752  // get failure flag
753  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
754  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
755  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
756 
757  if(!ffdehardfailure){
758  usedhotinversion=0;
759  usedentropyinversion=0;
760  usedcoldinversion=0;
761  usedffdeinversion=1;
762 
763  // report back that used this
764  *eomtype=EOMFFDE;
765 
766  // check ffde inversion if inversion thinks it was successful
767  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
768 
769  // adjust failure flag
770  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
771  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
772  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
773  }
774  }
775  }
776  else ffdepflag=1;
777 
778 
779 
780 
781  }
782  else if(eomtypelocal==EOMFFDE){
784  //
786  //
788 
789  // report back that used this
790  *eomtype=eomtypelocal;
791 
792 
793 
794  // GODMARK: inversions lead to different behavior (start with torus with rho=u=0 but loop of field)!
795 
796  ffdetried=1;
797  if(0){ // Jon's old inversion
798  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMFFDE, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
799  }
800  else if(1){
801  // Jon's inversion
802  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr,pressure,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
803  }
804  else if(0){
805  compare_ffde_inversions(showmessages, allowlocalfailurefixandnoreport,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Ugeomfree0, Ugeomfree, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
806  }
807  PLOOP(pliter,pl) ffdepr[pl]=pr[pl]; // save ffdepr
808 
809  if(ffdetried){
810 
811  // get failure flag
812  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
813  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
814  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
815 
816  if(!ffdehardfailure){
817  usedhotinversion=0;
818  usedentropyinversion=0;
819  usedcoldinversion=0;
820  usedffdeinversion=1;
821 
822  // report back that used this
823  *eomtype=EOMFFDE;
824 
825  // check ffde inversion if inversion thinks it was successful
826  check_on_inversion(checkoninversiongas, checkoninversionrad, usedhotinversion,usedentropyinversion,usedcoldinversion,usedffdeinversion,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr0, pr, pressure, ptrgeom, Uold, Unew,newtonstats,&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL));
827 
828  // adjust failure flag
829  ffdepflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
830  ffderadinvmod=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
831  ffdehardfailure=(IFUTOPRIMFAIL(ffdepflag) && IFUTOPRIMFAILSOFT(ffdepflag)==0);
832  }
833  }
834 
835  }//end if EOMFFDE
836 
837 
838 
839 
840 
841 
843  // USED BY IMPLICIT METHOD. BUT, currently disabled multiple tries (forcetry=0 always) since MODEPICKBEST now goes through each eomtype one at a time and we don't want to switch MHD inversions.
844  // pick best or use default pr
845  //
847  static long long int numpicks=0,didpickenergy=0,didpickentropy=0,didpicknormal=0,didpicknotbest=0;
848  if((whichmethod==MODEPICKBEST) && hottried && hothardfailure==0 && entropytried && entropyhardfailure==0){
849 
850 
851  // then based upon conditions, choose best result
852  // KORALTODO: Fake errors -- assumes these inversions always get lowest error desired.
853  int doentropy;
854  doentropy=whetherdoentropy(ptrgeom, fracenergy, !entropyhardfailure, !hothardfailure, entropyradinvmod, hotradinvmod, 1E-16, 1E-9, 1E-10, 1E-18, 1E-18, entropypr, hotpr);
855 
856  if(doentropy){
857  PLOOP(pliter,pl) pr[pl]=entropypr[pl];
858  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=entropypflag;
859  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=entropyradinvmod;
860  *eomtype=EOMENTROPYGRMHD;
861  didpickentropy++;
862  }
863  else if(!hothardfailure){
864  PLOOP(pliter,pl) pr[pl]=hotpr[pl];
865  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=hotpflag;
866  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=hotradinvmod;
867  *eomtype=EOMGRMHD;
868  didpickenergy++;
869  }
870  else{
871  // then sequence of conditionals decides which pr to use (i.e. whether to use entropy, hot, or cold)
872  didpicknormal++;
873  }
874  numpicks++;
875 
876  }
877  else{
878  // then sequence of conditionals leads to final pr[] having final desired inversion.
879  didpicknotbest++;
880  }
881 
882  if((whichmethod==MODEPICKBEST) && debugfail>=2) if(numpicks>0 && numpicks%(totalzones*REPORTCYCLE)==0) dualfprintf(fail_file,"DIDPICKS: %lld : %lld %lld %lld : %lld : %d\n",numpicks,didpickenergy,didpickentropy,didpicknormal,didpicknotbest,*eomtype);
883 
884 
885 
886 
887 
889  //
890  // modify failure flag if necessary
891  //
893 
894 #if(DOEVOLVERHO)
895  negdensitycheck(finalstep, pr, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL));
896 #endif
897 
898 
899 
900 
901 
902 
904  //
906  //
907  // complain if pflag set
908  // only output if failed
909  //
911 
912  // for now only report if not just negative density failure
913  lpflag=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
914  lpflagrad=GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
915 
916 
917 
918  if(IFUTOPRIMFAILSOFT(lpflag) || IFUTOPRIMRADFAIL(lpflagrad)){
919  // then don't report info for now SUPERGODMARK
920  if(showmessages&&debugfail>=1) dualfprintf(fail_file, "SOFT Failed to find a prim. var. solution on finalstep=%d!! t=%21.15g steppart=%d nstep=%ld i=%d j=%d k=%d : fail=%d : errx=%21.15g lpflagrad=%d\n",finalstep,t,steppart,realnstep,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,lpflag,newtonstats->lerrx,lpflagrad);
921  }
922  else if((IFUTOPRIMFAIL(lpflag) || IFUTOPRIMRADHARDFAIL(lpflagrad)) &&(debugfail>=1)){
923  if(showmessages) dualfprintf(fail_file, "Failed to find a prim. var. solution on finalstep=%d!! t=%21.15g steppart=%d nstep=%ld i=%d j=%d k=%d : fail=%d : errx=%21.15g lpflagrad=%d\n",finalstep,t,steppart,realnstep,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,lpflag,newtonstats->lerrx,lpflagrad);
924  }
925  else{
926  // if(showmessages) dualfprintf(fail_file, "NO FAIL t=%21.15g steppart=%d nstep=%ld i=%d j=%d k=%d : fail=%d : errx=%21.15g\n",t,steppart,realnstep,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,lpflag,newtonstats->lerrx,lpflagrad);
927  }
928 
929 
930 
931 
932 
933 
934 #if(PRODUCTION==0)
935 
936  //
938  //
940  debug_utoprimgen(&lpflag, pr0, pr, ptrgeom, Uold, Unew);
941 #endif
942 
943 
944 
945 
947  //
949  //
951  if(0){
952  if(preexistingfailgas) GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=preexistingfailgas;
953  if(preexistingfailrad) GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=preexistingfailrad;
954  // KORALTODO: Could further decide to use original pf from some point in source explicit/implicit updates instead of this no-force solution.
955  }
956  else{
957 
958  if(preexistingfailgas>0 || preexistingfailrad>0){
959 
960  // then accepting explicit as solution, do see how close got solution in diagnostics
961 
962  if(1||finalstep==1){// && GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)<=UTOPRIMNOFAIL && GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)<=UTOPRIMRADNOFAIL){
963  // see how accurately got energy-momentum
964  struct of_state qb;
965  get_state(pr,ptrgeom,&qb);
966  FTYPE ub[NPR],ubabs[NPR];
967  int uutype=UDIAG;
968  primtoU(uutype,pr,&qb,ptrgeom,ub,ubabs);
969  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
970  // dualfprintf(fail_file,"URHOINIMPLICIT=%21.15g\n",ub[RHO]*dx[1]*dx[2]*dx[3]);
971  // }
972 
973  FTYPE utot[NPR];
974  PLOOP(pliter,pl) utot[pl] = Ugeomfree0[pl]; // UNOTHING
975 
976  // dualfprintf(fail_file,"ub=%g utot=%g dU=%g\n",ub[UU],utot[UU],ub[UU]-utot[UU]);
977 
978  FTYPE ubdiag[NPR],utotdiag[NPR];
979  UtoU(UDIAG,UDIAG,ptrgeom,ub,ubdiag); // convert from UNOTHING -> UDIAG
980  UtoU(UNOTHING,UDIAG,ptrgeom,utot,utotdiag); // convert from UNOTHING -> UDIAG
981 
982 
983  PLOOP(pliter,pl) if(BPL(pl)) utotdiag[pl] = ubdiag[pl]; // cell center as if no change as required, but should be true already as setup these.
984 
985  // get optical depth
986  FTYPE tautot[NDIM],tautotmax;
987  calc_tautot(pr, ptrgeom, &qb, tautot, &tautotmax);
988 
989 
990  if(preexistingfailgas && (IFUTOPRIMFAILSOFT(lpflag) || IFUTOPRIMNOFAILORFIXED(lpflag) )){// then failed before but not with explicit
991 
992  // get bsqorho
993  FTYPE bsqorho;
994  FTYPE bsq; bsq_calc_fromq(pr, ptrgeom, &qb, &bsq);
995  bsqorho=bsq/pr[RHO];
996 
997 
998  FTYPE gammamaxlimit=0.9*GAMMAMAX;
999  FTYPE gamma,qsq;
1000  gamma_calc(pr,ptrgeom,&gamma,&qsq);
1001 
1002  // keep velocity if bsq/rho>1
1003  // if(bsqorho>1.0 && gamma<gammamaxlimit){
1004  if(bsqorho>BSQORHOLIMIT/5.0 && tautotmax<1E-1 && gamma<gammamaxlimit){
1005  // only fail densities, because velocity in high mag regime controls flux of magnetic flux-energy-momentum and don't want to just average that as that would unreasonably lose energy-momentum conservation
1006  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILURHO2AVG1FROMFFDE;
1007  // dualfprintf(fail_file,"MHD bsqhorho=%g avoided full failure: %d %d %d preexist=%d\n",bsqorho,ptrgeom->i,ptrgeom->j,ptrgeom->k,preexistingfailgas);
1008  }
1009  else{
1010  // revert fail
1011  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=preexistingfailgas;
1012  // dualfprintf(fail_file,"MHD1: bsqorho=%g %d %d : %d %d %d\n",bsqorho,preexistingfailgas,lpflag,ptrgeom->i,ptrgeom->j,ptrgeom->k);
1013  }
1014  }
1015  else{
1016  // dualfprintf(fail_file,"MHD2: %d %d\n",preexistingfailgas,lpflag);
1017  }
1018 
1019 
1020  //UTOPRIMRADFAILFIXEDUTOPRIMRAD
1021  if(preexistingfailrad && IFUTOPRIMRADNOFAIL(lpflagrad)){// then failed before but not with explicit
1022 
1023  FTYPE radgammamaxlimit=0.9*GAMMAMAXRAD;
1024  FTYPE radgamma,radqsq;
1025  gamma_calc(&pr[URAD1-U1],ptrgeom,&radgamma,&radqsq);
1026 
1027 
1028  if(tautotmax<1E-3 && radgamma<radgammamaxlimit){ // tautotmax<1 too aggressive, makes radiation go nuts.
1029  // fail density only
1030  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMFAILU2AVG1;
1031  // dualfprintf(fail_file,"RAD avoided full failure: %d %d %d: preexist=%d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,preexistingfailrad);
1032  }
1033  else{
1034  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=preexistingfailrad;
1035  // dualfprintf(fail_file,"RAD1: tau=%g %d %d : %d %d %d\n",tautotmax,preexistingfailgas,lpflag,ptrgeom->i,ptrgeom->j,ptrgeom->k);
1036  }
1037  }
1038  else{
1039  // dualfprintf(fail_file,"RAD2: %d %d\n",preexistingfailgas,lpflag);
1040  }
1041  // unlike gas velocity that links to both density and magnetic field, radiation is alone, so no point in making rad density averaged and not average velocity
1042  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=preexistingfailrad;
1043 
1044 
1045  // Get deltaUavg[] and also modify ucons if required and should
1046  int whocalled;
1047  whocalled=COUNTEXPLICITNORMAL;
1048 
1049 
1050  int docorrectuconslocal=0;
1051  extern int diag_fixup_dUandaccount(FTYPE *Ui, FTYPE *Uf, FTYPE *ucons, struct of_geom *ptrgeom, int finalstep, int whocalled, int docorrectuconslocal);
1052  diag_fixup_dUandaccount(utotdiag, ubdiag, NULL, ptrgeom, finalstep, whocalled, docorrectuconslocal);
1053 
1054 
1055  // FTYPE rat = fabs(utotdiag[RHO]-ubdiag[RHO])/(fabs(utotdiag[RHO])+fabs(ubdiag[RHO]));
1056  // if(rat>1E-13){
1057  // dualfprintf(fail_file,"Why not: %d %d %d : %21.15g %21.15g: diff=%21.15g : prho=%21.15g uu0RHO=%21.15g: error=%21.15g %21.15g\n",usedenergy,usedentropy,usedcold,utotdiag[RHO],ubdiag[RHO],utotdiag[RHO]-ubdiag[RHO],pb[RHO],uu0[RHO]*ptrgeom->gdet,errorabs[0],errorabs[1]);
1058  // }
1059 
1060  }
1061  else{
1062  // no solution, reverst to explicit and then average bad values, accounting will occur there.
1063  }
1064  }
1065  }
1066 
1067 
1069  //
1070  // if(nstep==4 && steppart==0){
1071  // PLOOP(pliter,pl) dualfprintf(fail_file,"PRIMUTOPRIMGEN1 (%d): pl=%d pp=%21.15g uu=%21.15g\n",*eomtype,pl,pr[pl],Ugeomfree[pl]);
1072  // }
1073 
1074 
1075 
1076 
1078  //
1079  // INVERT pseudo-passive scalars
1080  //
1081  // all pseudo-passive scalars are trivially inverted
1082  //
1083  // So don't include passive scalars in check_on_inversion() [Since modify passive scalars]
1084  //
1086  invert_scalars1(ptrgeom, Ugeomfree,pr);
1088  //
1089  // INVERT pseudo-passive scalars #2 (where u^t needed)
1090  //
1092  invert_scalars2(ptrgeom, Ugeomfree,NULL, pr);
1093 
1094 
1095  return(0);
1096 
1097 }
1098 
1099 
1100 
1101 
1102 
1103 
1104 
1105 
1107 int tryhotinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
1108 {
1109  int triedhot=0;
1110  int pl;
1111  FTYPE prentropy[NPR],prhot[NPR];
1112  PFTYPE hotpflag;
1113  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
1114  int eomtypelocal=EOMGRMHD;
1115 
1117  int TRYNEWIFOLDUNEG=1;
1119  int TRYNEWIFOLDRHONEG=1;
1121  int TRYNEWIFOLDFAILCONV=1;
1122 
1123 
1124  int badfailure;
1125  if( (TRYNEWIFOLDRHONEG==1 && IFUTOPRIMFAILSOFTRHORELATED(oldpflag)) || (TRYNEWIFOLDUNEG==1 && IFUTOPRIMFAILSOFTNOTRHORELATED(oldpflag)) || (TRYNEWIFOLDFAILCONV==1 && IFUTOPRIMFAIL(oldpflag)) ){
1126  // get here if want to fix up rho<=0, u<=0, or convergence failure
1127  // First if() is needed since last conditional or else if() would trigger on any failure type
1128  badfailure=1;
1129  }
1130  else{
1131  // then maybe not so bad failure
1132  // e.g. if get here, do nothing when either rho<=0 or u<=0
1133  badfailure=0;
1134  }
1135 
1136 
1137  if(badfailure || forcetry){
1138 
1139  // then bad failure or doing both energy and entropy, so try to use hot grmhd
1140  // restore backup in case previous inversion changed things
1141  PALLLOOP(pl){
1142  prentropy[pl]=pr[pl];
1143  Ugeomfree[pl]=Ugeomfree0[pl];
1144 
1145  // setup input guess and other already-inverted solutions
1146  if(badfailure==0 && forcetry) prhot[pl]=prentropy[pl]; // then use entropy as guess
1147  else prhot[pl]=pr0[pl];
1148  }
1149 
1151  // If just using pr/pr0 for guess, then fixup
1153  if(ENTROPYFIXGUESSEXTERNAL && modprim==1){
1154  // qptr is not final qptr, just previous from "pi" or at best "pb"
1155  entropyfixguess(qptr, ptrgeom, Ugeomfree, prhot);
1156  // also get highest out of current "flux" and "initial" step parts.
1157  prhot[UU]=MAX(fabs(prhot[UU]),fabs(pi[UU]));
1158  }
1159 
1160 
1161  // get hot evolution inversion
1162  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMVERSION, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &hotpflag, prhot,pressure,newtonstats, lpflagrad);
1163 
1164 
1166  //
1167  // check if hot solution is good
1168  if(IFUTOPRIMNOFAILORFIXED(hotpflag)){
1169 
1170 
1171  // set pflag so diag_fixup knows used hot inversion
1172  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILFIXEDUTOPRIM;
1173 
1174 
1175  // then keep hot solution
1176  PALLLOOP(pl) pr[pl]=prhot[pl];
1177 
1178 
1179  // accounting (since fixup.c accounting doesn't know what original pr0 is and actual prhot is undefined since Uhot->prhot wasn't possible)
1180  // GODMARK: For DOENOFLUX>0, should modify conserved quantity in some way. For DOENOFLUX==0, primitives form basis of conserved quantities, so once primitives are modified all is done. So should probably pass in U[] from Utoprimgen() or whatever is the full conserved quantity later used.
1181  int modcons=(DOENOFLUX != NOENOFLUX);
1182  FTYPE Uievolve[NPR];
1183  // ucons not modified (i.e. modcons=0), but ucons may be used by diag_fixup()
1184  UtoU(UNOTHING,UEVOLVE,ptrgeom,Ugeomfree0,Uievolve);
1185  // account for change to hot MHD conserved quantities
1186  // diag_fixup_Ui_pf(modcons,Uievolve,pr,ptrgeom,finalstep,COUNTHOT);
1187 
1188  // KORALTODO: allowlocalfailurefixandnoreport could be used below to avoid reset, but for now let implicit solver be ok with hot inversion
1189  // reset pflag, unless still need to do some kind of averaging
1190  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)==UTOPRIMFAILFIXEDUTOPRIM){
1191  // default then is that no failure
1192  // already accounted for and just a soft failure that doesn't require fixup anymore (and can't leave as UTOPRIMFAILFIXEDUTOPRIM since fixup would complain about not resetting the flag)
1193  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMNOFAIL;
1194  }
1195 
1196  triedhot=1;
1197 
1198 
1199  }// else if hotpflag is bad
1200  else{
1201  // then both entropy and hot are bad, so keep entropy
1202  // GODMARK: Could try going to force-free and "failing" the parallel velocity so it gets averaged like internal energy in hot case!
1203  // only can go to force-free if b^2/rho>>1 as well
1204  // keep entropypflag and keep entropy solution
1205  PALLLOOP(pl) pr[pl]=prentropy[pl];
1206 
1207 #if(PRODUCTION==0)
1208  if(forcetry==0 && debugfail>=2 && showmessages){
1209  dualfprintf(fail_file,"Tried hot and bad on finalstep=%d! t=%g steppart=%d nstep=%ld i=%d j=%d k=%d :: hotpflag=%d hotpflag=%d\n",finalstep,t,steppart,nstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,hotpflag,hotpflag);
1210  }
1211 
1212 #endif
1213 
1214  triedhot=0;
1215 
1216  }
1217 
1218  }// if bad failure of some kind
1219 
1220 
1221 
1222 
1223 
1224  return(triedhot);
1225 }
1226 
1227 
1228 
1229 
1230 
1232 int tryentropyinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
1233 {
1234  int triedentropy=0;
1235  int pl;
1236  FTYPE prold[NPR],prentropy[NPR];
1237  PFTYPE entropypflag;
1238  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
1239  int eomtypelocal=EOMENTROPYGRMHD;
1240 
1241  // dualfprintf(fail_file,"Got here in tryentropyinversion: oldpflag=%d\n",oldpflag);
1242 
1244  int TRYNEWIFOLDUNEG=1;
1246  int TRYNEWIFOLDRHONEG=1;
1248  int TRYNEWIFOLDFAILCONV=1;
1249 
1250  int badfailure;
1251  if( (TRYNEWIFOLDRHONEG==1 && IFUTOPRIMFAILSOFTRHORELATED(oldpflag)) || (TRYNEWIFOLDUNEG==1 && IFUTOPRIMFAILSOFTNOTRHORELATED(oldpflag)) || (TRYNEWIFOLDFAILCONV==1 && IFUTOPRIMFAIL(oldpflag)) ){
1252  // get here if want to fix up rho<=0, u<=0, or convergence failure
1253  // First if() is needed since last conditional or else if() would trigger on any failure type
1254  badfailure=1;
1255  }
1256  else{
1257  // then maybe not so bad failure
1258  // e.g. if get here, do nothing when either rho<=0 or u<=0
1259  badfailure=0;
1260  }
1261 
1262 
1263  triedentropy=0;
1264  if(badfailure || forcetry){
1265  triedentropy=1;
1266 
1267 
1268  // then bad failure, so try to use entropy grmhd
1269  // restore backup in case previous inversion changed things
1270  PALLLOOP(pl){
1271  prold[pl]=pr[pl];
1272  Ugeomfree[pl]=Ugeomfree0[pl];
1273 
1274  // setup input guess and other already-inverted solutions
1275  if(forcetry && badfailure==0) prentropy[pl]=prold[pl]; // use hot as guess since hot was actually good
1276  else prentropy[pl]=pr0[pl];
1277  }
1278 
1280  // If just using pr/pr0 for guess, then fixup
1282  if(ENTROPYFIXGUESSEXTERNAL && modprim==1){
1283  // qptr is not final qptr, just previous from "pi" or at best "pb"
1284  entropyfixguess(qptr, ptrgeom, Ugeomfree, prentropy);
1285  // also get highest out of current "flux" and "initial" step parts.
1286  prentropy[UU]=MAX(fabs(prentropy[UU]),fabs(pi[UU]));
1287  }
1288 
1289  // setup as if full entropy evolution
1290  int whichentropy=EVOLVEFULLENTROPY;
1291  // get entropy evolution inversion
1292  // EVOLVENOENTROPY
1293  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtypelocal, whichcap, whichentropy, Ugeomfree, ptrgeom, &entropypflag, prentropy,pressure,newtonstats, lpflagrad);
1294 
1295 
1297  //
1298  // check if entropy solution is good
1299  if(IFUTOPRIMNOFAILORFIXED(entropypflag)){
1300 
1301 
1302  // set pflag so diag_fixup knows used entropy inversion
1303  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILFIXEDENTROPY;
1304 
1305 
1306  // then keep entropy solution
1307  PALLLOOP(pl) pr[pl]=prentropy[pl];
1308 
1309 
1310  // accounting (since fixup.c accounting doesn't know what original pr0 is and actual prold is undefined since U->pr wasn't possible)
1311  // GODMARK: For DOENOFLUX>0, should modify conserved quantity in some way. For DOENOFLUX==0, primitives form basis of conserved quantities, so once primitives are modified all is done. So should probably pass in U[] from Utoprimgen() or whatever is the full conserved quantity later used.
1312  int modcons=(DOENOFLUX != NOENOFLUX);
1313  FTYPE Uievolve[NPR];
1314  // ucons not modified (i.e. modcons=0), but ucons may be used by diag_fixup()
1315  UtoU(UNOTHING,UEVOLVE,ptrgeom,Ugeomfree0,Uievolve);
1316  // account for change to hot MHD conserved quantities
1317  // diag_fixup_Ui_pf(modcons,Uievolve,pr,ptrgeom,finalstep,COUNTENTROPY);
1318 
1319  // KORALTODO: allowlocalfailurefixandnoreport could be used below to avoid reset, but for now let implicit solver be ok with entropy inversion
1320  // reset pflag, unless still need to do some kind of averaging
1321  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)==UTOPRIMFAILFIXEDENTROPY){
1322  // default then is that no failure
1323  // already accounted for and just a soft failure that doesn't require fixup anymore (and can't leave as UTOPRIMFAILFIXEDUTOPRIM since fixup would complain about not resetting the flag)
1324  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMNOFAIL;
1325  }
1326 
1327 
1328 
1329  // but set internal energy to previous value (should really evolve with entropy equation, but if negligible and no strong shocks, then ok )
1330  // GODMARK: another ok way is to set special failure that only averages internal energy! Then can evolve at least -- in some diffusive way
1331 #if(PRODUCTION==0)
1332  if(forcetry==0 && debugfail>=2 && showmessages) dualfprintf(fail_file,"Tried entropy and good on finalstep=%d! steppart=%d nstep=%ld i=%d j=%d k=%d :: oldpflag=%d entropypflag=%d\n",finalstep,steppart,nstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,oldpflag,entropypflag);
1333 
1334  if(debugfail>=2){
1335  // int pliter;
1336  // if(pr[UU]>1.0) dualfprintf(fail_file,"PDEATH\n");
1337  // if(pr[UU]<1E-13) dualfprintf(fail_file,"PDEATH2\n");
1338  // if(Ugeomfree0[ENTROPY]<-10) dualfprintf(fail_file,"PDEATH3\n");
1339  // PLOOP(pliter,pl) dualfprintf(fail_file,"POST GO TO ENTROPY: ijk=%d %d %d nstep=%ld steppart=%d pl=%d pr0=%g pr=%g U0=%g U=%g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,pl,pr0[pl],pr[pl],Ugeomfree0[pl],Ugeomfree[pl]);
1340 
1341  }
1342 #endif
1343 
1344 
1345 
1346  }// else if entropypflag is bad
1347  else{
1348  // then both hot and entropy are bad, so keep old
1349  // GODMARK: Could try going to force-free and "failing" the parallel velocity so it gets averaged like internal energy in entropy case!
1350  // only can go to force-free if b^2/rho>>1 as well
1351  // keep oldpflag and keep old solution
1352  PALLLOOP(pl) pr[pl]=prold[pl];
1353 
1354  // set how failed
1355  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=entropypflag;
1356 
1357 
1358 #if(PRODUCTION==0)
1359  if(forcetry==0 && debugfail>=2 && showmessages){
1360  dualfprintf(fail_file,"Tried entropy and bad on finalstep=%d! t=%g steppart=%d nstep=%ld i=%d j=%d k=%d :: oldpflag=%d entropypflag=%d\n",finalstep,t,steppart,nstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,oldpflag,entropypflag);
1361  // int pliter;
1362  // if(pr[UU]>1.0) dualfprintf(fail_file,"ADEATH\n");
1363  // if(pr[UU]<1E-13) dualfprintf(fail_file,"ADEATH2\n");
1364  // if(Ugeomfree0[ENTROPY]<-10) dualfprintf(fail_file,"ADEATH3\n");
1365  // PLOOP(pliter,pl) dualfprintf(fail_file,"POST DID NOT GO TO ENTROPY: ijk=%d %d %d nstep=%ld steppart=%d pl=%d pr0=%g pr=%g U0=%g U=%g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,pl,pr0[pl],pr[pl],Ugeomfree0[pl],Ugeomfree[pl]);
1366  }
1367 
1368 #endif
1369 
1370 
1371  }
1372 
1373  }// if bad failure of some kind
1374 
1375 
1376 
1377 
1378 
1379  return(triedentropy);
1380 }
1381 
1382 
1383 
1384 
1385 
1386 
1387 
1388 
1389 
1390 
1392 int trycoldinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
1393 {
1394  int coldtried;
1395  int pl;
1396  FTYPE prold[NPR],prcold[NPR];
1397  PFTYPE coldpflag;
1398  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
1399 
1400  // dualfprintf(fail_file,"Got here in trycoldinversion\n");
1401 
1403  int TRYNEWIFOLDUNEG=1;
1405  int TRYNEWIFOLDRHONEG=1;
1407  int TRYNEWIFOLDFAILCONV=1;
1408 
1409 
1410  int badfailure;
1411  if( (TRYNEWIFOLDRHONEG==1 && IFUTOPRIMFAILSOFTRHORELATED(oldpflag)) || (TRYNEWIFOLDUNEG==1 && IFUTOPRIMFAILSOFTNOTRHORELATED(oldpflag)) || (TRYNEWIFOLDFAILCONV==1 && IFUTOPRIMFAIL(oldpflag)) ){
1412  // get here if want to fix up rho<=0, u<=0, or convergence failure
1413  // First if() is needed since last conditional or else if() would trigger on any failure type
1414  badfailure=1;
1415  }
1416  else{
1417  // then maybe not so bad failure
1418  // e.g. if get here, do nothing when either rho<=0 or u<=0
1419  badfailure=0;
1420  }
1421 
1422 
1423 
1424  // see if cold inversion makes sense to do
1425  int includerad=0; // just MHD inversion here
1426  FTYPE COLDFACTOR=0.1; // try to make use cold to order unity errors
1427  int iscoldflow=isflowcold(COLDFACTOR, includerad, pr0, ptrgeom, qptr, NULL);
1428  if(iscoldflow==0) if(debugfail>=2) dualfprintf(fail_file,"in trycoldinversion but iscoldflow=0\n");
1429 
1430 
1431  coldtried=0;
1432  if((badfailure || forcetry)&&iscoldflow){
1433  coldtried=1;
1434 
1435 
1436  // then bad failure, so try to use cold grmhd
1437  // restore backup in case previous inversion changed things
1438  PALLLOOP(pl){
1439  prold[pl]=pr[pl];
1440  Ugeomfree[pl]=Ugeomfree0[pl];
1441 
1442  // set guess and sets any pre-inverted quantities
1443  prcold[pl]=pr0[pl];
1444  }
1445 
1446 
1447  // get cold inversion
1448  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, EOMCOLDGRMHD, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &coldpflag, prcold,pressure,newtonstats, lpflagrad);
1449 
1450 
1451  // check also if gamma hit beyond maximum
1452  FTYPE gamma,qsq;
1453  gamma_calc(pr,ptrgeom,&gamma,&qsq);
1454  if(gamma>GAMMAMAX) coldpflag=UTOPRIMFAILGENERIC;
1455 
1456 
1458  //
1459  // check if cold solution is good
1460  if(IFUTOPRIMNOFAILORFIXED(coldpflag)){
1461 
1462  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILFIXEDCOLD; // default then is that no failure (or fixed failure)
1463 
1464  // then keep cold solution
1465  PALLLOOP(pl) pr[pl]=prcold[pl];
1466  // if internal energy is not negligible or unknown, then should average or evolve!
1467  pl=UU; pr[pl] = pr0[pl]; // but keep u_g from prior hot.
1468 
1469 
1470  // but set internal energy to previous value (should really evolve with entropy equation, but if negligible and no strong shocks, then ok )
1471  // GODMARK: another ok way is to set special failure that only averages internal energy! Then can evolve at least -- in some diffusive way
1472 
1473 #if(PRODUCTION==0)
1474  if(forcetry==0 && debugfail>=2) dualfprintf(fail_file,"Tried cold and good on finalstep=%d! i=%d j=%d k=%d :: oldpflag=%d coldpflag=%d\n",finalstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,oldpflag,coldpflag);
1475  // if(debugfail>=2){
1476  // if(pr[RHO]<0.0 || pr[UU]<0.0) PALLLOOP(pl) dualfprintf(fail_file,"pl=%d pr=%g\n",pl,pr[pl]);
1477  // if(gamma>2.0) dualfprintf(fail_file,"gamma=%g\n",gamma);
1478  // }
1479 #endif
1480 
1482  //
1483  // decide how to use cold inversion solution
1484  if(0&&IFUTOPRIMFAILSOFTNOTRHORELATED(oldpflag)){ // avoided now since reverting to 0 can introduce extra structure. Want to keep to using averaging if possible that will generate better solution.
1485  // since cold approximation is very good, then use cold solution and just set internal energy to 0
1486  // if internal energy is actually small, then just set it to 0
1487  // works for Hubble flow!
1488  pr[UU]=zerouuperbaryon*pr[RHO];
1489  }
1490  else{
1492  // then very bad failure, so try cold inversion and average internal energy for now
1493  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILU2AVG1FROMCOLD; // assume only internal energy needs correcting by averaging
1494 
1495  }// end if (else) trying cold inversion
1496 
1497 
1498 
1499 
1500 
1501  // accounting (since fixup.c accounting doesn't know what original pr0 is and actual prold is undefined since U->pr wasn't possible)
1502  // GODMARK: For DOENOFLUX>0, should modify conserved quantity in some way. For DOENOFLUX==0, primitives form basis of conserved quantities, so once primitives are modified all is done. So should probably pass in U[] from Utoprimgen() or whatever is the full conserved quantity later used.
1503  int modcons=(DOENOFLUX != NOENOFLUX);
1504  FTYPE Ui[NPR];
1505  // ucons not modified (i.e. modcons=0), but ucons may be used by diag_fixup()
1506  UtoU(UNOTHING,UDIAG,ptrgeom,Ugeomfree0,Ui);
1507  // account for change to hot MHD conserved quantities
1508  int counttype;
1509  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)!=UTOPRIMFAILFIXEDCOLD) counttype=COUNTCOLD; // count if not going to be counted later
1510  else counttype=COUNTNOTHING; // do correction, but don't do counting until later
1511  // diag_fixup_Ui_pf(modcons,Ui,pr,ptrgeom,finalstep,counttype);
1512 
1513  // KORALTODO: allowlocalfailurefixandnoreport could be used below to avoid reset, but for now let implicit solver be ok with cold inversion
1514  // reset pflag since above does full accounting, unless need to average-out internal energy still
1515  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)==UTOPRIMFAILFIXEDCOLD){
1516  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMNOFAIL;
1517  }
1518 
1519  }// else if coldpflag is bad
1520  else{
1521 
1522  // set how failed
1523  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=coldpflag;
1524 
1525 
1526  // then both hot and cold are bad, so keep old
1527  // GODMARK: Could try going to force-free and "failing" the parallel velocity so it gets averaged like internal energy in cold case!
1528  // only can go to force-free if b^2/rho>>1 as well
1529  // keep oldpflag and keep old solution
1530  PALLLOOP(pl) pr[pl]=prold[pl];
1531 
1532 #if(PRODUCTION==0)
1533  if(forcetry==0 && debugfail>=2) dualfprintf(fail_file,"Tried cold and bad on finalstep=%d! t=%g steppart=%d nstep=%ld i=%d j=%d k=%d :: oldpflag=%d coldpflag=%d\n",finalstep,t,steppart,nstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,oldpflag,coldpflag);
1534 #endif
1535 
1536 
1537  }
1538 
1539  }// if bad failure of some kind
1540 
1541  return(coldtried);
1542 }
1543 
1544 
1545 
1546 
1547 
1548 
1549 
1551 int tryffdeinversion(int showmessages, int allowlocalfailurefixandnoreport, int finalstep, PFTYPE oldpflag, int forcetry, int whichcap, int modprim, FTYPE *pi, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, FTYPE *Ugeomfree, FTYPE *Ugeomfree0, struct of_state *qptr, struct of_geom *ptrgeom, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
1552 {
1553  int ffdetried;
1554  int pl;
1555  FTYPE prold[NPR],prffde[NPR];
1556  PFTYPE ffdepflag;
1557  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
1558 
1559 
1560  // dualfprintf(fail_file,"Got here in tryffdeinversion\n");
1561 
1563  int TRYNEWIFOLDUNEG=0;
1565  int TRYNEWIFOLDRHONEG=0;
1567  int TRYNEWIFOLDFAILCONV=1;
1568 
1569  int badfailure;
1570  if( (TRYNEWIFOLDRHONEG==1 && IFUTOPRIMFAILSOFTRHORELATED(oldpflag)) || (TRYNEWIFOLDUNEG==1 && IFUTOPRIMFAILSOFTNOTRHORELATED(oldpflag)) || (TRYNEWIFOLDFAILCONV==1 && IFUTOPRIMFAIL(oldpflag)) ){
1571  // get here if want to fix up rho<=0, u<=0, or convergence failure
1572  // First if() is needed since last conditional or else if() would trigger on any failure type
1573  badfailure=1;
1574  }
1575  else{
1576  // then maybe not so bad failure
1577  // e.g. if get here, do nothing when either rho<=0 or u<=0
1578  badfailure=0;
1579  }
1580 
1581 
1582 
1583  // see if ffde inversion makes sense to do
1584  int includerad=0; // just MHD inversion here
1585  FTYPE FFDEFACTOR=0.5; // try to make use ffde to order unity errors
1587  FTYPE V[NDIM];
1588  bl_coord_ijk(ptrgeom->i,ptrgeom->j,ptrgeom->k,CENT,V);
1589  if(V[1]<Rhor) FFDEFACTOR=5.0; // more aggressive inside horizon to keep field evolving
1590  }
1591  int isffdeflow=isflowffde(FFDEFACTOR, pr0, qptr);
1592  if(isffdeflow==0) if(debugfail>=2) dualfprintf(fail_file,"in tryffdeinversion but isffdeflow=0\n");
1593 
1594 
1595 
1596  ffdetried=0;
1597  if((badfailure || forcetry)&&isffdeflow){
1598  ffdetried=1;
1599 
1600 
1601  // then bad failure, so try to use ffde grmhd
1602  // restore backup in case previous inversion changed things
1603  PALLLOOP(pl){
1604  prold[pl]=pr[pl];
1605  Ugeomfree[pl]=Ugeomfree0[pl];
1606 
1607  // set guess and sets any pre-inverted quantities
1608  prffde[pl]=pr0[pl];
1609  }
1610 
1611 
1612  // get ffde inversion
1613  // NOTEMARK: Note use of EOMFFDE2 instead of EOMFFDE because FFDE used always from originally having density, so using non-cleaned version that uses initial W.
1614  // REVERT to just EOMFFDE since current EOMFFDE2 (or 2nd version in utoprim_jon.c) is worse behavior for \gamma and bsq.
1615  // Well, as long as only include W and not Q.B, does better than including Q.B, but still worse than just EOMFFDE
1616  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, EOMFFDE, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &ffdepflag, prffde,pressure,newtonstats, lpflagrad);
1617 
1618 
1620  //
1621  // check if ffde solution is good
1622  if(IFUTOPRIMNOFAILORFIXED(ffdepflag)){
1623 
1624  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILFIXEDFFDE; // default then is that no failure (or fixed failure)
1625 
1626  // then keep ffde solution
1627  PALLLOOP(pl) pr[pl]=prffde[pl];
1628  // if rho or u_g are not negligible or unknown, then should average or evolve!
1629  pl=RHO; pr[pl] = pr0[pl]; // but keep rho from prior hot.
1630  pl=UU; pr[pl] = pr0[pl]; // but keep u_g from prior hot.
1631  // EOMFFDE2 above tries to keep evolve v.B value.
1632 
1633 
1634 
1635  // but set internal energy to previous value (should really evolve with entropy equation, but if negligible and no strong shocks, then ok )
1636  // GODMARK: another ok way is to set special failure that only averages internal energy! Then can evolve at least -- in some diffusive way
1637 
1638 #if(PRODUCTION==0)
1639  if(forcetry==0 && debugfail>=2) dualfprintf(fail_file,"Tried ffde and good on finalstep=%d! i=%d j=%d k=%d :: oldpflag=%d ffdepflag=%d\n",finalstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,oldpflag,ffdepflag);
1640 #endif
1641 
1643  // then very bad failure, so try ffde inversion and average internal energy for now
1644  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMFAILURHO2AVG1FROMFFDE; // assume only internal energy needs correcting by averaging
1645 
1646 
1647 
1648 
1649 
1650 
1651  // accounting (since fixup.c accounting doesn't know what original pr0 is and actual prold is undefined since U->pr wasn't possible)
1652  // GODMARK: For DOENOFLUX>0, should modify conserved quantity in some way. For DOENOFLUX==0, primitives form basis of conserved quantities, so once primitives are modified all is done. So should probably pass in U[] from Utoprimgen() or whatever is the full conserved quantity later used.
1653  int modcons=(DOENOFLUX != NOENOFLUX);
1654  FTYPE Ui[NPR];
1655  // ucons not modified (i.e. modcons=0), but ucons may be used by diag_fixup()
1656  UtoU(UNOTHING,UDIAG,ptrgeom,Ugeomfree0,Ui);
1657  // account for change to hot MHD conserved quantities
1658  int counttype;
1659  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)!=UTOPRIMFAILFIXEDFFDE) counttype=COUNTFFDE;
1660  else counttype=COUNTNOTHING; // do correction, but don't do counting until later
1661  // diag_fixup_Ui_pf(modcons,Ui,pr,ptrgeom,finalstep,counttype);
1662 
1663  // KORALTODO: allowlocalfailurefixandnoreport could be used below to avoid reset, but for now let implicit solver be ok with ffde inversion
1664  // reset pflag since above does full accounting, unless need to average-out internal energy still
1665  if(GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)==UTOPRIMFAILFIXEDFFDE){
1666  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMNOFAIL;
1667  }
1668 
1669 
1670  }// else if ffdepflag is bad
1671  else{
1672 
1673  // set how failed
1674  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=ffdepflag;
1675 
1676  // then both hot and ffde are bad, so keep old
1677  // GODMARK: Could try going to force-free and "failing" the parallel velocity so it gets averaged like internal energy in ffde case!
1678  // only can go to force-free if b^2/rho>>1 as well
1679  // keep oldpflag and keep old solution
1680  PALLLOOP(pl) pr[pl]=prold[pl];
1681 
1682 #if(PRODUCTION==0)
1683  if(forcetry==0 && debugfail>=2) dualfprintf(fail_file,"Tried ffde and bad on finalstep=%d! t=%g steppart=%d nstep=%ld i=%d j=%d k=%d :: oldpflag=%d ffdepflag=%d\n",finalstep,t,steppart,nstep,ptrgeom->i,ptrgeom->j,ptrgeom->k,oldpflag,ffdepflag);
1684 #endif
1685 
1686 
1687  }
1688 
1689  }// if bad failure of some kind
1690 
1691  return(ffdetried);
1692 }
1693 
1694 
1695 
1696 
1697 
1698 
1699 
1700 
1701 
1702 
1709 static int check_on_inversion(int checkoninversiongas, int checkoninversionrad, int usedhotinversion,int usedentropyinversion,int usedcoldinversion,int usedffdeinversion, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_geom *ptrgeom, FTYPE *Uold, FTYPE *Unew, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
1710 {
1711  int badinversion,badinversionfail;
1712  int badinversionrad,badinversionfailrad;
1713  FTYPE Unormalnew[NPR],Unormalnewabs[NPR],Unormalold[NPR];
1714  FTYPE fdiff[NPR];
1715  struct of_state q;
1716  int pl,pliter;
1717  int j,k,jj;
1718  FTYPE errornorm;
1719 
1720 
1721  // see if should check at all
1722  if(checkoninversiongas==0 && checkoninversionrad==0) return(0);
1723 
1724 
1725 
1727  //
1728  // Store extra quantities to enforce consistency when using tabulated EOS
1729  //
1731 
1732  if(WHICHEOS==KAZFULL && ptrgeom->p==CENT){
1733  // then store pressure to be used by get_stateforcheckinversion()
1734  // assume standard inversion at loc=CENT
1735  GLOBALMACP0A1(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k,PGASGLOBAL)=(*pressure);
1736  }
1737 
1738 
1739  FTYPE prtest[NPR];
1740  // since need to modify best version of pr for different eomtype's, use prtest locally
1741  PLOOP(pliter,pl) prtest[pl] = pr[pl];
1742 
1743 
1744  // force test to be clean true inversion
1745  if(usedcoldinversion || usedffdeinversion){
1746  prtest[UU] = 0.0;
1747  if(WHICHEOS==KAZFULL && ptrgeom->p==CENT){
1748  GLOBALMACP0A1(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k,PGASGLOBAL)=0.0;
1749  }
1750  }
1751  if(usedffdeinversion){
1752  prtest[RHO]=0.0;
1753  }
1754 
1755 
1756  // assume not bad
1757  badinversion=badinversionfail=0;
1758  badinversionrad=badinversionfailrad=0;
1759 
1760 
1761 
1762  // if(1 || !(*lpflag)){ // only report if not failure and not fixup (in which case U might differ)
1763  if(*lpflag==0 || *lpflagrad==0){ // only report if not failure and not fixup (in which case U might differ)
1764 
1766  //
1767  // get new U (only applicable if hot inversion used)
1768  //
1770  MYFUN(get_stateforcheckinversion(prtest, ptrgeom, &q),"flux.c:fluxcalc()", "get_state()", 1);
1771  FTYPE Unewabs[NPR];
1772  MYFUN(primtoU(UNOTHING,prtest, &q, ptrgeom, Unew, Unewabs),"step_ch.c:advance()", "primtoU()", 1); // UtoU inside doesn't do anything...therefore for REMOVERESTMASSFROMUU==1, Unew[UU] will have rest-mass included
1773 
1775  //
1776  // Create a normalized (geometrically) conserved quantity
1777  //
1779  // assume default value assignment for normalized version of U
1780  PLOOP(pliter,pl){
1781  Unormalold[pl] = Uold[pl];
1782  Unormalnew[pl] = Unew[pl];
1783  Unormalnewabs[pl] = Unewabs[pl];
1784  }
1785 
1786 #if(REMOVERESTMASSFROMUU==2)
1787  // now make U_0 and U_i comparable
1788  // like \rho\gamma^2 v^2/(1+\gamma) + (u+p)\gamma^2 \sim \rho \gamma v^2 + (u+p)\gamma^2
1789  // In the limit as v->0, this can be compared against the normalized version of the U_i terms
1790  Unormalold[UU] = Uold[UU];
1791  Unormalnew[UU] = Unew[UU];
1792  Unormalnewabs[UU] = Unewabs[UU];
1793 
1794  // No longer doing below, just use gcon or gcov to get correct dimensional comparison
1795  // now deal with momentum terms and correct for geometry so all U_i's are comparable
1796  // (\rho+u+p)\gamma u_i -> (\rho+u+p)\gamma^2 v^2
1797  // SLOOPA(jj) Unormalold[UU+jj] = Uold[UU+jj]*(q.ucon[jj]/q.ucon[TT]);
1798  // SLOOPA(jj) Unormalnew[UU+jj] = Unew[UU+jj]*(q.ucon[jj]/q.ucon[TT]);
1799  // SLOOPA(jj) Unormalnewabs[UU+jj] = Unewabs[UU+jj]*(q.ucon[jj]/q.ucon[TT]);
1800 #endif
1801 
1802 
1803 
1805  //
1806  // now check for errors
1807  //
1809  PLOOP(pliter,pl){
1810 
1811  if(checkoninversiongas==0 && (pl!=PRAD0 && pl!=PRAD1 && pl!=PRAD2 && pl!=PRAD3)) continue; // don't check MHD (non-radiation) inversion if didn't want to
1812  if(checkoninversionrad==0 && (pl==PRAD0 && pl==PRAD1 && pl==PRAD2 && pl==PRAD3)) continue; // don't check radiation (non-MHD) inversion if didn't want to
1813 
1814 
1815  // default is to assume nothing wrong
1816  fdiff[pl]=0.0;
1817 
1818 
1819  // pl here is conserved quantity, so checking if conserved quantity not same as used to get primitive
1820  // in force-free projection on velocity always occurs that makes momenta terms not the same
1821  // no point checking if inversion doesn't handle or is inconsistent with conservation of that quantity
1822  if(usedffdeinversion && (pl==RHO || pl==UU || pl==U1 || pl==U2 || pl==U3 || pl==ENTROPY || SCALARPL(pl)) ) continue; // if ffde, no mass or thermal/hot components
1823  if(usedcoldinversion && (pl==UU || pl==ENTROPY || SCALARPL(pl)) ) continue; // if cold, can't evolve any hot or thermal component
1824  // inversion either uses energy or entropy and can't use both at once inside inversion routine
1825  if(usedentropyinversion && (pl==UU) ) continue; // entropy doesn't use energy equation, but does use conserved entropy
1826  if(usedhotinversion && (pl==ENTROPY) ) continue; // hot doesn't use entropy, but does use conserved energy
1827 
1828  //(EOMRADTYPE==EOMRADNONE && (pl==URAD0 || pl==URAD1 || pl==URAD2 || pl==URAD3)) || // no need to check pl if no such pl's
1829  // lpflagrad: Checks that if u2p placed limiter on p (e.g. velocity), then should skip this check since won't be accurate inversion
1830  if(EOMRADTYPE!=EOMRADNONE && (*lpflagrad!=0)) continue;
1831  // If doing Eddington approximation, actually ignore conserved flux evolution.
1832  if(EOMRADTYPE==EOMRADEDD && (pl==URAD1 || pl==URAD2 || pl==URAD3)) continue;
1833 
1834 
1835  if(SCALARPL(pl)){
1836  // only check that new U is finite
1837  if(!isfinite(Unormalnew[pl])){
1838  fdiff[pl]=BIG; // indicates was not finite
1839  }
1840  else continue; // then avoid checking passive scalars in case manipulated
1841  }
1842 
1843  // leave geometry out of it
1844  // Unormalnew[pl]*=ptrgeom->gdet;
1845  // Unormalold[pl]*=ptrgeom->gdet;
1846  if(pl==RHO || pl==UU || pl==URAD0&&(*lpflagrad==0)){
1847  errornorm=(fabs(Unormalnewabs[pl])+fabs(Unormalnew[pl])+fabs(Unormalold[pl])+SMALL);
1848  // KORALTODO: when URAD0<<UU, can't expect radiation error to be small relative to only itself when interaction between radiation and fluid.
1849  if(pl==URAD0) errornorm+=(fabs(Unormalnewabs[UU])+fabs(Unormalnew[UU])+fabs(Unormalold[UU])+SMALL);
1850  fdiff[pl] = fabs(Unormalnew[pl]-Unormalold[pl])/errornorm;
1851  }
1852  else if(pl==ENTROPY){
1853  // can be + or -, so use positive definite exp(S/rho)=exp(s) version
1854  // errornorm=(fabs(exp(Unormalnew[pl]/(SMALL+fabs(Unormalnew[RHO]))))+fabs(exp(Unormalold[pl]/(SMALL+fabs(Unormalold[RHO]))))+SMALL);
1855  // fdiff[pl] = fabs(exp(Unormalnew[pl]/(SMALL+fabs(Unormalnew[RHO])))-exp(Unormalold[pl]/(SMALL+fabs(Unormalold[RHO]))))/errornorm;
1856  // TdS / (TdS + E)
1857  FTYPE Tgasnew=compute_temp_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,prtest[RHO],prtest[UU]);
1858  FTYPE Tgasold=compute_temp_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pr0[RHO],pr0[UU]);
1859  errornorm=(fabs(Tgasnew)+fabs(Tgasold))*(fabs(Unormalnewabs[pl])+fabs(Unormalnew[pl])+fabs(Unormalold[pl])+SMALL) + (fabs(Unormalnewabs[UU])+fabs(Unormalnew[UU])+fabs(Unormalold[UU])+SMALL);
1860  fdiff[pl] = (fabs(Tgasnew)+fabs(Tgasold))*fabs(Unormalnew[pl]-Unormalold[pl])/errornorm;
1861  }
1862  else if(pl==U1 || pl==U2 || pl==U3){
1863 
1864  errornorm = THIRD*THIRD*(
1865  +(fabs(Unormalnewabs[U1]) + fabs(Unormalnew[U1]) + fabs(Unormalold[U1]))*sqrt(fabs(ptrgeom->gcon[GIND(1,1)]))
1866  +(fabs(Unormalnewabs[U2]) + fabs(Unormalnew[U2]) + fabs(Unormalold[U2]))*sqrt(fabs(ptrgeom->gcon[GIND(2,2)]))
1867  +(fabs(Unormalnewabs[U3]) + fabs(Unormalnew[U3]) + fabs(Unormalold[U3]))*sqrt(fabs(ptrgeom->gcon[GIND(3,3)]))
1868  );
1869 #if(REMOVERESTMASSFROMUU==2)
1870  // only valid comparison if rest-mass taken out of energy term and modify U_i term to be comparable with U_t term
1871  errornorm = MAX(errornorm,THIRD*(fabs(Unormalold[UU])+fabs(Unormalnew[UU])+fabs(Unormalnewabs[UU])));
1872 #endif
1873  fdiff[pl] = sqrt(fabs(ptrgeom->gcon[GIND(pl-UU,pl-UU)]))*fabs(Unormalnew[pl]-Unormalold[pl]) / (errornorm+SMALL);
1874 
1875  }
1876  else if( (pl==URAD1 || pl==URAD2 || pl==URAD3)&&(*lpflagrad==0) ){
1877  // errornorm = THIRD*(fabs(Unormalnew[URAD1])+fabs(Unormalold[URAD1])+fabs(Unormalnew[URAD2])+fabs(Unormalold[URAD2])+fabs(Unormalnew[URAD3])+fabs(Unormalold[URAD3]));
1878  errornorm = THIRD*THIRD*(
1879  +(fabs(Unormalnewabs[URAD1]) + fabs(Unormalnew[URAD1]) + fabs(Unormalold[URAD1]))*sqrt(fabs(ptrgeom->gcon[GIND(1,1)]))
1880  +(fabs(Unormalnewabs[URAD2]) + fabs(Unormalnew[URAD2]) + fabs(Unormalold[URAD2]))*sqrt(fabs(ptrgeom->gcon[GIND(2,2)]))
1881  +(fabs(Unormalnewabs[URAD3]) + fabs(Unormalnew[URAD3]) + fabs(Unormalold[URAD3]))*sqrt(fabs(ptrgeom->gcon[GIND(3,3)]))
1882  );
1883  // KORALTODO: when URAD0<<UU, can't expect radiation error to be small relative to only itself when interaction between radiation and fluid.
1884  errornorm += THIRD*THIRD*(
1885  +(fabs(Unormalnewabs[U1]) + fabs(Unormalnew[U1]) + fabs(Unormalold[U1]))*sqrt(fabs(ptrgeom->gcon[GIND(1,1)]))
1886  +(fabs(Unormalnewabs[U2]) + fabs(Unormalnew[U2]) + fabs(Unormalold[U2]))*sqrt(fabs(ptrgeom->gcon[GIND(2,2)]))
1887  +(fabs(Unormalnewabs[U3]) + fabs(Unormalnew[U3]) + fabs(Unormalold[U3]))*sqrt(fabs(ptrgeom->gcon[GIND(3,3)]))
1888  );
1889  errornorm = MAX(errornorm,0.5*(fabs(Unormalold[URAD0])+fabs(Unormalnew[URAD0])+fabs(Unormalnewabs[URAD0])));
1890 
1891  fdiff[pl] = sqrt(fabs(ptrgeom->gcon[GIND(pl-URAD0,pl-URAD0)]))*fabs(Unormalnew[pl]-Unormalold[pl]) / (errornorm+SMALL);
1892  }
1893  else if(pl==B1 || pl==B2 || pl==B3){
1894  errornorm = THIRD*THIRD*(
1895  +(fabs(Unormalnewabs[B1]) + fabs(Unormalnew[B1]) + fabs(Unormalold[B1]))*sqrt(fabs(ptrgeom->gcon[GIND(1,1)]))
1896  +(fabs(Unormalnewabs[B2]) + fabs(Unormalnew[B2]) + fabs(Unormalold[B2]))*sqrt(fabs(ptrgeom->gcon[GIND(2,2)]))
1897  +(fabs(Unormalnewabs[B3]) + fabs(Unormalnew[B3]) + fabs(Unormalold[B3]))*sqrt(fabs(ptrgeom->gcon[GIND(3,3)]))
1898  );
1899  fdiff[pl] = sqrt(fabs(ptrgeom->gcov[GIND(pl-B1+1,pl-B1+1)]))*fabs(Unormalnew[pl]-Unormalold[pl]) / (errornorm+KINDASMALL); // for field order 1E-100 or less, geometry division and multiplication causes this to shift in value by order unity.
1900  }
1901  }
1902 
1903 
1904 
1905  // broke loop to check multiple directions
1906 
1907 
1908  int plcheck;
1909  PLOOP(pliter,pl){
1910 
1911 #if(0)
1912  if((IFUTOPRIMFAIL(*lpflag) || checkoninversiongas==0) && (pl!=PRAD0 && pl!=PRAD1 && pl!=PRAD2 && pl!=PRAD3)) continue; // don't check MHD (non-radiation) inversion if didn't want to
1913  if((IFUTOPRIMRADHARDFAIL(*lpflagrad) || checkoninversionrad==0) && (pl==PRAD0 && pl==PRAD1 && pl==PRAD2 && pl==PRAD3)) continue; // don't check radiation (non-MHD) inversion if didn't want to
1914 
1915 
1916  plcheck=(pl>=RHO)&&(pl<=B3 || pl<=ENTROPY && usedentropyinversion || (*lpflagrad==0)&&(EOMRADTYPE!=EOMRADNONE && (pl==URAD0 || pl==URAD1&&(EOMRADTYPE!=EOMRADEDD) || pl==URAD2&&(EOMRADTYPE!=EOMRADEDD) || pl==URAD3&&(EOMRADTYPE!=EOMRADEDD) )));
1917 #endif
1918  // if fdiff=0.0, then didn't set or no problems
1919  plcheck=(fdiff[pl]!=0.0);
1920 
1921  // if(IFUTOPRIMFAIL(*lpflag) || fdiff[pl]>CHECKONINVFRAC){
1922  if(fdiff[pl]>CHECKONINVFRAC){
1923  if(
1924  ( (plcheck)&&((fabs(Unormalold[pl])>SMALL)&&(fabs(Unormalnew[pl])>SMALL)) )
1925  ){
1926  if(pl<URAD0 && pl>URAD3) badinversion++;
1927  else badinversionrad++;
1928 
1929  if(debugfail>=2){
1930  if(pl==ENTROPY) dualfprintf(fail_file,"fdiff[%d]=%21.15g :: %21.15g %21.15g : %21.15g %21.15g : %21.15g %21.15g\n",pl,fdiff[pl],Unormalold[pl],Unormalnew[pl],exp(Unormalold[pl]/Unormalold[RHO]),exp(Unormalnew[pl]/Unormalnew[RHO]),Unormalold[RHO],Unormalnew[RHO]);
1931  else dualfprintf(fail_file,"fdiff[%d]=%21.15g :: %21.15g %21.15g\n",pl,fdiff[pl],Unormalold[pl],Unormalnew[pl]);
1932  }
1933 
1934  }
1935  }
1936  if(fdiff[pl]>CHECKONINVFRACFAIL){
1937  if( (plcheck)&&((fabs(Unormalold[pl])>SMALL)&&(fabs(Unormalnew[pl])>SMALL)) ){
1938  if(pl<URAD0 && pl>URAD3) badinversionfail++;
1939  else badinversionfailrad++;
1940  }
1941  }
1942 
1943 
1944  // dualfprintf(fail_file,"pl=%d Uold=%26.20g Unew=%26.20g\n",pl,Unormalold[pl],Unormalnew[pl]);
1945 
1946 
1947  }
1948 
1950  //
1951  // change failure flag if really bad check
1952  //
1954  if(checkoninversiongas==1 && FAILIFBADCHECK && badinversionfail){
1955  if(debugfail>=2) dualfprintf(fail_file,"Changing flag since sufficiently bad inversion.\n");
1957  }
1958  // checkoninversionrad==1 case: No, would not redo inversion since no reduction to another inversion.
1959 
1960 
1961 
1963  //
1964  // Account for any conserved quantity change (could be just difference created by primtoU, but still tells order of issue)
1965  //
1966  // only makes sense to account for changes in U if inversion is treated as success
1967  //
1968  // Also, only makes sense if using primitives as basis. Since, if use U as basis, then each iteration relies upon old correct U without any error introduced due to inversion.
1969  //
1971 
1972 
1973 
1975  //
1976  // Report bad inversion
1977  //
1979 
1980  // if(myid==5 && nstep==1 && steppart==0 && ptrgeom->i==19 && ptrgeom->j==15){
1981  // badinversion=1;
1982  // }
1983 
1984  if(badinversion || badinversionrad){
1985 
1986  if(debugfail>=2){
1987  dualfprintf(fail_file,"Bad inversion (or possibly Bad U(p) calculation):\n");
1988  dualfprintf(fail_file,"Inversion types: %d %d %d %d\n",usedffdeinversion,usedcoldinversion,usedentropyinversion,usedhotinversion);
1989 
1990  dualfprintf(fail_file,"t=%21.15g nstep=%ld stepart=%d :: i=%d j=%d k=%d :: lntries=%d lerrx=%21.15g\n",t,nstep,steppart,ptrgeom->i,ptrgeom->j,ptrgeom->k,newtonstats->lntries,newtonstats->lerrx);
1991  PLOOP(pliter,pl) dualfprintf(fail_file,"Uoldgeomfree[%d]=%21.15g Unewgeomfree[%d]=%21.15g pr[%d]=%21.15g prtest[%d]=%21.15g (pr0[%d]=%21.15g) fdiff=%21.15g\n",pl,Uold[pl],pl,Unew[pl],pl,pr[pl],prtest[pl],pl,pr0[pl],fdiff[pl]);
1992  dualfprintf(fail_file,"special inversion pressure=%21.15g statepressure=%21.15g stateentropy=%21.15g\n",*pressure,q.pressure,q.entropy);
1993 
1994  dualfprintf(fail_file,"g=%21.15g\n",ptrgeom->gdet);
1995 
1996  DLOOP(j,k) dualfprintf(fail_file,"gcov=%21.15g gcon=%21.15g\n",ptrgeom->gcov[GIND(j,k)],ptrgeom->gcon[GIND(j,k)]);
1997 
1998  DLOOPA(k) dualfprintf(fail_file,"k=%d : q.ucon=%21.15g q.ucov=%21.15g : q.uradcon=%21.15g q.uradcov=%21.15g : q.bcon=%21.15g q.bcov=%21.15g\n",k,q.ucon[k],q.ucov[k],q.uradcon[k],q.uradcov[k],q.bcon[k],q.bcov[k]);
1999  }
2000 
2001 #if(0)
2002  // not using these anymore, and only set by utoprim_jon.c
2003  // only really need the below quantities to check on inversion in mathematica
2004  // Use Eprime_inversion.nb to check on utoprim_jon.c inversion
2005  for(j=0;j<NUMINVPROPERTY;j++) dualfprintf(fail_file,"%sstr=\"%21.15g\";\n",newtonstats->invpropertytext[j],newtonstats->invproperty[j]);
2006 #endif
2007  }
2008 
2009  }
2010 
2011  // if(ptrgeom->i==39){
2012  // PLOOP(pliter,pl) dualfprintf(fail_file,"i=%d : pl=%d Uold=%21.15g Unew=%21.15g pr0=%21.15g pr=%21.15g\n",ptrgeom->i,pl,Uold[pl],Unew[pl],pr0[pl],pr[pl]);
2013  // }
2014 
2015 
2016  return(0);
2017 
2018 
2019 }
2020 
2021 
2022 
2023 
2024 
2025 
2026 
2027 
2028 
2029 
2030 
2031 
2032 
2033 
2034 
2035 
2036 
2038 static int compare_ffde_inversions(int showmessages, int allowlocalfailurefixandnoreport, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_geom *ptrgeom, FTYPE *Ugeomfree0, FTYPE*Ugeomfree, FTYPE *Uold, FTYPE *Unew, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
2039 {
2040  int j,k;
2041  int pl;
2042  FTYPE prother[NPR];
2043  FTYPE Upr[NPR],Uprother[NPR];
2044  struct of_state q;
2045  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
2046  int eomtypelocal=EOMTYPE; // as chosen before introduced eomtypelocal
2047  int whichcap=CAPTYPEBASIC;
2048 
2049  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMFFDE, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), pr, pressure, newtonstats,lpflagrad);
2050 
2051  PALLLOOP(pl) Ugeomfree[pl]=Ugeomfree0[pl]; // make sure good conserved quantity
2052 
2053  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtypelocal, whichcap, EVOLVENOENTROPY, Ugeomfree, ptrgeom, &GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL), prother, pressure, newtonstats, lpflagrad);
2054 
2055 
2056  // now get conserved quantity from pr to check
2057  // find U(p)
2058  MYFUN(get_state(pr, ptrgeom, &q),"step_ch.c:advance()", "get_state()", 1);
2059  MYFUN(primtoU(UNOTHING,pr, &q, ptrgeom, Upr, NULL),"step_ch.c:advance()", "primtoU()", 1);
2060 
2061  MYFUN(get_state(prother, ptrgeom, &q),"step_ch.c:advance()", "get_state()", 1);
2062  MYFUN(primtoU(UNOTHING,prother, &q, ptrgeom, Uprother, NULL),"step_ch.c:advance()", "primtoU()", 1);
2063 
2064 
2065  // now compare
2066 
2067  //PALLLOOP(pl)
2068  dualfprintf(fail_file,"nstep=%ld stepart=%d i=%d j=%d\n",nstep,steppart,ptrgeom->i,ptrgeom->j);
2069  for(pl=U1;pl<B3;pl++){
2070  /*
2071  if(
2072  ((fabs(Ugeomfree[pl]-Upr[pl])/(fabs(Ugeomfree[pl])+fabs(Upr[pl])+SMALL)) > 1E-12)||
2073  ((fabs(Ugeomfree[pl]-Uprother[pl])/(fabs(Ugeomfree[pl])+fabs(Uprother[pl])+SMALL)) > 1E-12)
2074  ){
2075  dualfprintf(fail_file,"DIFF: %21.15g %21.15g ::pl=%d Ugeomfree=%21.15g prold=%21.15g prnew=%21.15g Upr=%21.15g Uprother=%21.15g\n",(fabs(Ugeomfree[pl]-Upr[pl])/(fabs(Ugeomfree[pl])+fabs(Upr[pl])+SMALL)),(fabs(Ugeomfree[pl]-Uprother[pl])/(fabs(Ugeomfree[pl])+fabs(Uprother[pl])+SMALL)),pl,Ugeomfree[pl],pr[pl],prother[pl],Upr[pl],Uprother[pl]);
2076  }
2077  */
2078  if(
2079  ((fabs(pr[pl]-prother[pl])/(fabs(pr[pl])+fabs(prother[pl])+SMALL)) > 1E-12)&&( (fabs(pr[pl])>1E-15)||(fabs(prother[pl])>1E-15) )
2080  ){
2081  dualfprintf(fail_file,"DIFF: %21.15g :: pl=%d Ugeomfree=%21.15g prold=%21.15g prnew=%21.15g Upr=%21.15g Uprother=%21.15g\n",(fabs(pr[pl]-prother[pl])/(fabs(pr[pl])+fabs(prother[pl])+SMALL)),pl,Ugeomfree[pl],pr[pl],prother[pl],Upr[pl],Uprother[pl]);
2082  }
2083  }
2084 
2085 
2086  return(0);
2087 
2088 }
2089 
2090 
2091 
2092 
2094 static int debug_utoprimgen(PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, struct of_geom *ptrgeom, FTYPE *Uold, FTYPE *Unew)
2095 {
2096  int j,k;
2097  int pl;
2098  FTYPE fdiff[NPR];
2099 
2100 
2101 
2102 
2103 
2104 
2105 #define CRAZYDEBUG 0
2106 #if(CRAZYDEBUG) // begin crazy debug stuff
2107  if(1|| newtonstats->lntries>3){
2108  if(nstep==9 && steppart==2 && ptrgeom->i==0 && ptrgeom->j==31){
2109  // if(nstep==0 && steppart==0 && ptrgeom->i==4 && ptrgeom->j==36){
2110  // if(nstep==0 && steppart==0 && ptrgeom->i == 5 && ptrgeom->j == 31 ){
2111  dualfprintf(fail_file,"nstep=%ld stepart=%d :: i=%d j=%d :: lntries=%d\n",nstep,steppart,ptrgeom->i,ptrgeom->j,newtonstats->lntries);
2112 
2113  // PALLLOOP(pl) dualfprintf(fail_file,"Ugeomfree[%d]=%21.15g pr[%d]=%21.15g\n",pl,Ugeomfree[pl],pl,pr[pl]);
2114  PALLLOOP(pl) dualfprintf(fail_file,"Uoldgeomfree[%d]=%21.15g Uold[%d]=%21.15g pr[%d]=%21.15g (pr0[%d]=%21.15g)\n",pl,Uold[pl],pl,Uold[pl]*ptrgeom->gdet,pl,pr[pl],pl,pr0[pl]);
2115 
2116  dualfprintf(fail_file,"g=%21.15g\n",ptrgeom->gdet);
2117 
2118  DLOOP(j,k) dualfprintf(fail_file,"gcon=%21.15g gcov=%21.15g\n",ptrgeom->gcov[GIND(j,k)],ptrgeom->gcon[GIND(j,k)]);
2119  // myexit(777);
2120  // }
2121  }
2122  }
2123 
2124 
2125  // test inversion for accuracy in conservative space
2126  // if(nstep==0 && steppart==0 && ptrgeom->i == 4 && ptrgeom->j == 36 ){
2127  if(nstep==9 && steppart==2 && ptrgeom->i==0 && ptrgeom->j==31){
2128 
2129 #if(0)
2130  pr[0]= 7.22714301361038e-06 ;
2131  pr[1]=-2.55753797775927e-07 ;
2132  pr[2]= 0.000892168434512681 ;
2133  pr[3]= -0.0349621334882251 ;
2134  pr[4]= -0 ;
2135  pr[5]= -0.00101880685475446 ;
2136  pr[6]= 0.0399035382308458 ;
2137  pr[7]= 0 ;
2138 #elif(0)
2139  pr[0]= 7.46157819677347e-06;
2140  pr[1]= 7.3407120498644e-06;
2141  pr[2]= 0.000367464781319951;
2142  pr[3]= -0.0144105143008605;
2143  pr[4]= 0;
2144  pr[5]= -0.00101880685475446;
2145  pr[6]= 0.0399035382308458;
2146  pr[7]= 0;
2147 #elif(0)
2148  pr[0]= 7.5124289176258e-06 ;
2149  pr[1]= 1.33752037209996e-08 ;
2150  pr[2]= 1.33529579432262e-07 ;
2151  pr[3]=-5.23276639757274e-06 ;
2152  pr[4]= 0 ;
2153  pr[5]= -0.00101880685475444 ;
2154  pr[6]= 0.0399035382308459 ;
2155  pr[7]= 0 ;
2156 
2157 #endif
2158 
2159  MYFUN(get_state(pr, ptrgeom, &q),"flux.c:fluxcalc()", "get_state()", 1);
2160  MYFUN(primtoU(UNOTHING,pr, &q, ptrgeom, Unew, NULL),"step_ch.c:advance()", "primtoU()", 1); // UtoU inside doesn't do anything...therefore for REMOVERESTMASSFROMUU==1, Unew[UU] will have rest-mass included
2161 
2162  for(k=0;k<4;k++){
2163  dualfprintf(fail_file,"q.ucon[%d]=%21.15g q.ucov[%d]=%21.15g q.bcon[%d]=%21.15g q.bcov[%d]=%21.15g\n",k,q.ucon[k],k,q.ucov[k],k,q.bcon[k],k,q.bcov[k]);
2164  }
2165 
2166  PLOOP(pliter,pl){
2167  Unew[pl]*=ptrgeom->gdet;
2168  Uold[pl]*=ptrgeom->gdet;
2169  fdiff[pl] = fabs(Unew[pl]-Uold[pl])/(fabs(Unew[pl]+Uold[pl])+SMALL);
2170  // if(fdiff[pl]>1E-10){
2171  if((pl>=RHO)&&(pl<=B3)&&((fabs(Uold[pl])>1E-20)||(fabs(Unew[pl])>1E-20))){
2172  dualfprintf(fail_file,"fdiff[%d]=%21.15g :: %21.15g %21.15g\n",pl,fdiff[pl],Uold[pl],Unew[pl]);
2173  }
2174  // }
2175  }
2176 
2177  dualfprintf(fail_file,"dt=%21.15g\n",dt);
2178 
2179 
2180  myexit(124);
2181  }
2182 #endif// end crazy debug stuff
2183 #undef CRAZYDEBUG
2184 
2185 
2186  return(0);
2187 
2188 
2189 }
2190 
2191 
2192 
2193 
2195 static int negdensitycheck(int finalstep, FTYPE *prim, PFTYPE *pflag)
2196 {
2197 
2198 
2199  //Inversion from the average value succeeded or has a negative density or internal energy
2200  if(IFUTOPRIMFAILSOFT(*pflag)) {
2201 
2202  if( prim[UU] < zerouuperbaryon*prim[RHO] && (finalstep&&STEPOVERNEGU==NEGDENSITY_FIXONFULLSTEP) || STEPOVERNEGU==NEGDENSITY_ALWAYSFIXUP) {
2203  *pflag = UTOPRIMFAILU2AVG2;
2204  }
2205  }
2206 
2207  return(0);
2208 }
2209 
2210 
2211 
2212 
2213 
2215 int invert_scalars1(struct of_geom *ptrgeom, FTYPE *Ugeomfree, FTYPE *pr)
2216 {
2217  FTYPE myrhouu0,oneOmyrhouu0;
2218  int i,j,k,loc;
2219  FTYPE prforadvect;
2220  FTYPE ylforadvect,ynuforadvect;
2221 
2222 
2223 
2224  i=ptrgeom->i;
2225  j=ptrgeom->j;
2226  k=ptrgeom->k;
2227  loc=ptrgeom->p;
2228 
2229 
2230 
2232  //
2233  // avoid division by 0 but allow sign and 1/0 ->0 assumed 0 geometry means value can be taken to be 0
2234  //
2236  myrhouu0=Ugeomfree[RHO];
2237  oneOmyrhouu0=sign(Ugeomfree[RHO])/(fabs(Ugeomfree[RHO])+SMALL);
2238 
2239 
2240 
2241 
2243  //
2244  // Invert U->direct Primitive for scalars
2245  //
2247 
2248 #if(DOYL!=DONOYL)
2249  ylforadvect = Ugeomfree[YL]*oneOmyrhouu0;
2250 #else
2251  ylforadvect=0.0;
2252 #endif
2253 
2254 #if(DOYNU!=DONOYNU)
2255  ynuforadvect = Ugeomfree[YNU]*oneOmyrhouu0;
2256 #else
2257  ynuforadvect=0.0;
2258 #endif
2259 
2261  //
2262  // Invert U->P for scalars
2263  //
2265 
2266 
2267 #if(DOYL!=DONOYL)
2268 #if(WHICHEOS==KAZFULL)
2269  advect2yl_kazfull(GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),ylforadvect,ynuforadvect,&pr[YE]); // pr[YE] is pr[YL] memory space
2270 #else
2271  pr[YL] = ylforadvect;
2272 #endif
2273 #endif
2274 
2275 #if(DOYNU!=DONOYNU)
2276 #if(WHICHEOS==KAZFULL)
2277  advect2ynu_kazfull(GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),ylforadvect,ynuforadvect,&pr[YNU]);
2278 #else
2279  pr[YNU] = ynuforadvect;
2280 #endif
2281 #endif
2282 
2283 
2284 
2286  //
2287  // Change the primitives to be constrained or fixed-up. Also perform any extra operations required by the EOS used.
2288  //
2290  fix_primitive_eos_scalars_simple(i,j,k,loc,pr);
2291 
2292 
2293 
2295  //
2296  // Adjust conserved quantities based upon fixed-up primitives
2297  //
2299 
2300 #if(DOYFL==1)
2301 
2302 #if(YFL1>=0)
2303  pr[YFL1] = Ugeomfree[YFL1]*oneOmyrhouu0;
2304 #endif
2305 #if(YFL2>=0)
2306  pr[YFL2] = -Ugeomfree[YFL2]*oneOmyrhouu0; // NOTEMARK: Same sign as in other places like fixup.c and elsewhere here in this file.
2307 #endif
2308 #if(YFL3>=0)
2309  pr[YFL3] = Ugeomfree[YFL3]*oneOmyrhouu0;
2310 #endif
2311  // below make no sense
2312  //#if(YFL4>=0)
2313  // pr[YFL4] = -Ugeomfree[YFL4]*oneOmyrhouu0;
2314  //#endif
2315  //#if(YFL5>=0)
2316  // pr[YFL5] = Ugeomfree[YFL5]*oneOmyrhouu0;
2317  //#endif
2318 
2319 #endif
2320 
2321 
2322 
2323 
2324 #if(DOYL!=DONOYL)
2325 #if(WHICHEOS==KAZFULL)
2326  yl2advect_kazfull(GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),pr[YL],pr[YNU],&prforadvect);
2327 #else
2328  prforadvect = pr[YL];
2329 #endif
2330  Ugeomfree[YL] = prforadvect*myrhouu0;
2331 #endif
2332 
2333 #if(DOYNU!=DONOYNU)
2334 #if(WHICHEOS==KAZFULL)
2335  ynu2advect_kazfull(GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),pr[YL],pr[YNU],&prforadvect);
2336 #else
2337  prforadvect = pr[YNU];
2338 #endif
2339  Ugeomfree[YNU] = prforadvect*myrhouu0;
2340 #endif
2341 
2342 
2343  // SUPER TODO: Consider if need to recompute KAZ EOSextra stuff for fluxes. Maybe now with primitives as lookups, interpolations correct. But need to ensure assignments to EOSextra for Y_e and Ynu0 is correctly done. Can leave neutrino stuff as "DONOR" cell
2344 
2345  return(0);
2346 }
2347 
2348 
2349 
2350 
2351 
2353 int invert_scalars2(struct of_geom *ptrgeom, FTYPE *Ugeomfree, struct of_state *q, FTYPE *pr)
2354 {
2355  int i,j,k,loc;
2356 
2357  i=ptrgeom->i;
2358  j=ptrgeom->j;
2359  k=ptrgeom->k;
2360  loc=ptrgeom->p;
2361 
2362 
2363  // get u^t
2365  // FTYPE uradcon[NDIM],othersrad[NUMOTHERSTATERESULTS];
2366  if(q==NULL){
2367  ucon_calc(pr,ptrgeom,ucon,others);
2368  // if(EOMRADTYPE!=EOMRADNONE && (YFL4>=0||YFL5>=0) ){
2369  // ucon_calc(&pr[URAD1-U1],ptrgeom,uradcon,othersrad);
2370  // }
2371  }
2372  else{
2373  ucon[TT] = q->ucon[TT];
2374  // uradcon[TT] = q->uradcon[TT];
2375  }
2376 
2377  FTYPE udir[NPR]={0.0};
2378  udir[YFL1]=udir[YFL2]=udir[YFL3]=ucon[TT];
2379  // udir[YFL4]=udir[YFL5]=uradcon[TT];
2380 
2381 
2383  //
2384  // Invert U->direct Primitive for scalars (in rhopart form rather than y=rhopart/rhototal form)
2385  //
2387 
2388 #if(DOYFL==2)
2389  if(YFL1>=0) pr[YFL1] = Ugeomfree[YFL1]/udir[YFL1];
2390  if(YFL2>=0){
2391  pr[YFL2] = -Ugeomfree[YFL2]/udir[YFL2]; // NOTEMARK: Same sign as in other places like fixup.c and elsewhere here in this file.
2392  if(pr[YFL2]<UULIMIT) pr[YFL2]=UULIMIT;
2393  }
2394  if(YFL3>=0) pr[YFL3] = Ugeomfree[YFL3]/udir[YFL3];
2395  // if(YFL4>=0) pr[YFL4] = -Ugeomfree[YFL4]/udir[YFL4];
2396  // if(YFL5>=0) pr[YFL5] = Ugeomfree[YFL5]/udir[YFL5];
2397 #endif
2398 
2399 
2400 
2401  return(0);
2402 }
2403 
2404 
2405 
2406 
2407 
2409 void convert_U_removerestmassfromuu(int utoprimversion, int removerestmassfromuu, FTYPE *U)
2410 {
2411 
2413  //
2415  //
2416  // check if inversion is chosen consistent with REMOVERESTMASSFROMUU
2417  // At this point, Ugeomfree[UU] in "standard form with rest-mass" for REMOVERESTMASSFROMUU=0,1. If ==2, then no rest-mass
2418  //
2420 
2421  if(removerestmassfromuu==2){
2422  // 5D1 handles removerestmassfromuu internally
2423  // NONRELCOMPAT only accepts UU without rest-mass, so good to go
2424  if( utoprimversion!=UTOPRIM5D1 && (utoprimversion!=UTOPRIMJONNONRELCOMPAT) ){
2425  // dualfprintf(fail_file,"This code does not handle removerestmassfromuu==2: other Utoprim's besides 5D1 and 2DFINAL\n");
2426  // myexit(1);
2427  // then change conserved quantity so can work
2428  U[UU]-=U[RHO]; // "add in rest-mass" so in correct form
2429  }
2430  }
2431  else if(removerestmassfromuu==0 || removerestmassfromuu==1){
2432  if(utoprimversion==UTOPRIMJONNONRELCOMPAT){
2433  // then change conserved quantity so can work for UTOPRIMJONNONRELCOMPAT
2434  U[UU]+=U[RHO]; // "subtract out rest-mass" so in correct form for NONRELCOMPAT
2435  }
2436  }
2437 
2438 
2439 }
2440 
2441 
2442 
2443 
2444 
2445 
2446 
2447 
2448 
2449 
2451 int Utoprimdiss(int showmessages, int allowlocalfailurefixandnoreport, int evolvetype, int inputtype,FTYPE *U, struct of_geom *ptrgeom, FTYPE *pr, PFTYPE *otherpflag, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
2452 {
2453  // debug
2454  int i, j, k;
2455  FTYPE Ugeomfree[NPR],Ugeomfree0[NPR];
2456  FTYPE pr0[NPR];
2457  FTYPE prother[NPR];
2458  FTYPE Upr[NPR],Uprother[NPR];
2459  int whichentropy;
2460  struct of_state q;
2461  FTYPE Uold[NPR],Unew[NPR];
2462  FTYPE fdiff[NPR];
2463  extern void UtoU(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
2464  int pl,pliter;
2465  FTYPE pressuremem;
2466  FTYPE *pressure=&pressuremem;
2467  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
2468  int eomtypelocal=EOMTYPE; // as chosen before introduced eomtypelocal
2469  int whichcap=CAPTYPEBASIC;
2470 
2471 
2472 
2473 
2474  // Notice that reconstruct "standard" geometry-free conserved quantities by first modifying the geometry prefactor and THEN dealing with rest-mass or other subtractions and additions.
2475  // This is consistent with primtoflux() and how primtoflux() is used in source_conn().
2476  UtoU(inputtype,UNOTHING,ptrgeom,U,Ugeomfree);
2477 
2478 
2480  //
2481  // backup
2482  //
2484  PALLLOOP(pl){
2485  Uold[pl]=Ugeomfree0[pl]=Ugeomfree[pl];
2486  pr0[pl]=pr[pl];
2487  }
2488 
2489 
2491  //
2492  // convert U into form appropriate for inversion routine (probably does nothing since assume UTOPRIM5D1 used) and feed Utprim Uold anyways
2493  //
2495  convert_U_removerestmassfromuu(UTOPRIM5D1,REMOVERESTMASSFROMUU,Ugeomfree);
2496  convert_U_removerestmassfromuu(UTOPRIM5D1,REMOVERESTMASSFROMUU,Ugeomfree0);
2497 
2498 
2500  //
2501  // DO INVERSION
2502 
2503  // assume solution is good unless flagged as bad
2504  *otherpflag=UTOPRIMNOFAIL;
2505 
2506  // do separate inversion for entropy version of EOMs
2507  // only one inversion is setup to handle this
2508  whichentropy=WHICHENTROPYEVOLVE;
2509 
2511  // get entropy evolution (don't use failure -- otherpflag)
2512  // this inversion knows about global settings for DOENTROPY and increases tolerance for doing comparison
2513  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIM5D1, eomtypelocal, whichcap, whichentropy, Uold, ptrgeom, otherpflag, pr, pressure, newtonstats, lpflagrad);
2514 
2515  // DEBUG:
2516  // PLOOP(pliter,pl) dualfprintf(fail_file,"otherpflag=%d Uold[%d]=%21.15g pr0[%d]=%21.15g pr[%d]=%21.15g\n",*otherpflag,pl,Uold[pl],pl,pr0[pl], pl,pr[pl]);
2517 
2518 
2519  // now get conserved quantity from pr to check
2520  // find U(p)
2521  // MYFUN(get_state(pr, ptrgeom, &q),"step_ch.c:advance()", "get_state()", 1);
2522  // MYFUN(primtoU(UNOTHING,pr, &q, ptrgeom, Unew, NULL),"step_ch.c:advance()", "primtoU()", 1);
2523 
2524 
2525  // if(0&& *otherpflag){
2526  // PLOOP(pliter,pl){
2527  // fdiff[pl] = fabs(Unew[pl]-Uold[pl])/(fabs(Unew[pl]+Uold[pl])+1E-30);
2528  // if(fdiff[pl]>1E-10){
2529  // if((pl>=U1)&&(pl<=B3)&&((fabs(Uold[pl])>1E-20)||(fabs(Unew[pl])>1E-20))){
2530  // dualfprintf(fail_file,"fdiff[%d]=%21.15g :: %g %g\n",pl,fdiff[pl],Uold[pl],Unew[pl]);
2531  // }
2532  // }
2533  // }
2534  // }
2535 
2536 
2537  return(0);
2538 }
2539 
2540 
2541 
2542 
2543 
2544 
2548 int Utoprimgen_compare(int showmessages, int allowlocalfailurefixandnoreport, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
2549 {
2550  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
2551  int pl,pliter;
2552  FTYPE Uo1[NPR], Uo2[NPR];
2553  FTYPE ptest1[NPR],ptest2[NPR];
2554  FTYPE Uo[NPR], po[NPR];
2555  int test;
2556  PFTYPE lpflag1,lpflag2;
2557  int lntries1,lntries2;
2558  FTYPE lerrx1,lerrx2;
2559  FTYPE pressure1mem,pressure2mem;
2560  FTYPE *pressure1=&pressure1mem,*pressure2=&pressure2mem;
2561 
2562  // backup
2563  PALLLOOP(pl){
2564  ptest1[pl]=ptest2[pl]=pr[pl];
2565  Uo1[pl]=Uo2[pl]=Ugeomfree[pl];
2566  }
2567 
2568  // currently comparing 5D1 and LDZ
2569  // Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIM5D1, eomtype, whichcap, EVOLVENOENTROPY, Uo1, ptrgeom, lpflag, ptest1,newtonstats, lpflagrad);
2570  // Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMLDZ, eomtype, whichcap, EVOLVENOENTROPY, Uo2, ptrgeom, lpflag, ptest2,newtonstats, lpflagrad);
2571 
2572  // remove rest-mass
2573  Uo1[UU]+=Uo1[RHO];
2574  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtype, whichcap, EVOLVENOENTROPY, Uo1, ptrgeom, &lpflag1, ptest1,pressure1,newtonstats,lpflagrad);
2575  lntries1=newtonstats->lntries; newtonstats->lntries=0; lerrx1=newtonstats->lerrx;
2576  Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, UTOPRIM2DFINAL, eomtype, whichcap, EVOLVENOENTROPY, Uo2, ptrgeom, &lpflag2, ptest2,pressure2,newtonstats,lpflagrad);
2577  lntries2=newtonstats->lntries; lerrx2=newtonstats->lerrx;
2578 
2579 #define ERRORCONST (1E-10)
2580 
2581  PALLLOOP(pl){
2582  if(ptest1[pl]!=0.0) test=fabs(ptest1[pl]-ptest2[pl])/ptest1[pl]>ERRORCONST;
2583  else test=(ptest1[pl]-ptest2[pl])>ERRORCONST;
2584  if(test){
2585  dualfprintf(fail_file,"utoprimdiff: %d %ld :: %d %d %d :: %d :: %21.15g %21.15g %21.15g %21.15g :: %d %d :: %21.15g %21.15g\n",steppart,nstep,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,pl,ptest1[pl]-ptest2[pl],(ptest1[pl]!=0.0) ? fabs(ptest1[pl]-ptest2[pl])/ptest1[pl] : ptest1[pl]-ptest2[pl],ptest1[pl],ptest2[pl],lntries1,lntries2,lerrx1,lerrx2);
2586  }
2587  }
2588  if(IFUTOPRIMFAIL(lpflag1) || IFUTOPRIMFAIL(lpflag2)){
2589  dualfprintf(fail_file,"%d %ld :: %d %d %d :: lpflag1=%d lpflag2=%d errx1=%21.15g errx2=%21.15g\n",steppart,nstep,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,lpflag1,lpflag2,lerrx1,lerrx2);
2590  }
2591  if(lntries1>10 || lntries2>10){
2592  dualfprintf(fail_file,"%d %ld :: %d %d %d :: lpflag1=%d lpflag2=%d errx1=%21.15g errx2=%21.15g lntries1=%d lntries2=%d\n",steppart,nstep,startpos[1]+ptrgeom->i,startpos[2]+ptrgeom->j,startpos[3]+ptrgeom->k,lpflag1,lpflag2,lerrx1,lerrx2,lntries1,lntries2);
2593  }
2594 
2595 
2596  // always do (use old utoprim)
2597  if(IFUTOPRIMNOFAILORFIXED(lpflag1)) PALLLOOP(pl){
2598  pr[pl]=ptest1[pl];
2599  *lpflag=lpflag1;
2600  }
2601  else{
2602  PALLLOOP(pl) pr[pl]=ptest2[pl];
2603  *lpflag=lpflag2;
2604  }
2605 
2606 
2607 
2608  return(0);
2609 }
2610 
2611 
2612 
2613 
2615 int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats,PFTYPE *lpflagrad)
2616 {
2617  extern int Utoprim_ffde(FTYPE *U, struct of_geom *geom, FTYPE *pr);
2618  extern int Utoprim_coldgrmhd(FTYPE *U, struct of_geom *geom, FTYPE *pr, int *positivityproblem);
2619  int positivityproblem;
2620  int pliter,pl;
2621 
2622 
2623 
2624  // FTYPE Ugeomfree0[NPR];
2625  // if(ptrgeom->i==10 && ptrgeom->k==0){
2626  // PLOOP(pliter,pl) Ugeomfree0[pl]=Ugeomfree[pl];
2627  // PLOOP(pliter,pl) dualfprintf(fail_file,"before inversion: pl=%d pr=%g\n",pl,pr[pl]);
2628  // if(pr[UU]>0.1) dualfprintf(fail_file,"beforeADEATHUU: ijk=%d %d %d u=%g %g (%g)\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[UU],Ugeomfree[UU],Ugeomfree0[UU]);
2629  // if(fabs(pr[U1])>1.0) dualfprintf(fail_file,"beforeADEATHU1: ijk=%d %d %d u=%g %g (%g)\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[U1],Ugeomfree[U1],Ugeomfree0[U1]);
2630  // }
2631 
2632 
2634  //
2635  // do fluid inversion
2636  //
2638 
2639  // below is only one that uses parameter to choose whether entropy inversion or not
2640  if(which==UTOPRIM5D1){ MYFUN(Utoprim(parameter,Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim", 1);}
2641  else if(which==UTOPRIMLDZ){ MYFUN(Utoprim_ldz(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_ldz", 1);}
2642  else if(which==UTOPRIM2D){ MYFUN(Utoprim_2d(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_2d", 1);}
2643  else if(which==UTOPRIM1D){ MYFUN(Utoprim_1d(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_1d", 1);}
2644  else if(which==UTOPRIM1DOPT){ MYFUN(Utoprim_1d_opt(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_1d_opt", 1);}
2645  else if(which==UTOPRIM1DFINAL){ MYFUN(Utoprim_1d_final(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_1d_final", 1);}
2646  else if(which==UTOPRIM2DFINAL){ MYFUN(Utoprim_2d_final(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_2d_final", 1);}
2647  // Below Jon's method handles full hotMHD, entropy, and coldMHD via setting eomtype (doesn't use parameter)
2648  else if(which==UTOPRIMJONNONRELCOMPAT){ MYFUN(Utoprim_jon_nonrelcompat_inputnorestmass(showmessages,eomtype,GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_2d_final_nonrelcompat_inputnorestmass", 1);}
2649  else if(which==UTOPRIM5D2){ MYFUN(Utoprim_5d2_final(Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats),"step_ch.c:Utoprimgen()", "Utoprim_5d2_final", 1);}
2650  // alt (not really working) inversion for coldmhd (alt compared to UTOPRIMJONNONRELCOMPAT)
2651  else if(which==UTOPRIMCOLDGRMHD){ MYFUN(Utoprim_coldgrmhd(Ugeomfree, ptrgeom, pr,&positivityproblem),"step_ch.c:Utoprimgen()", "Utoprim_ffde", 1);}
2652  // alt force-free inversion (alt compared to UTOPRIMJONNONRELCOMPAT)
2653  else if(which==UTOPRIMFFDE){ MYFUN(Utoprim_ffde(Ugeomfree, ptrgeom, pr),"step_ch.c:Utoprimgen()", "Utoprim_ffde", 1);}
2654  else{
2655  dualfprintf(fail_file,"No such which=%d in Utoprimgen_pick()\n");
2656  myexit(1769384215);
2657  }
2658 
2659 
2660  // if(ptrgeom->i==10 && ptrgeom->k==0){
2661  // PLOOP(pliter,pl) dualfprintf(fail_file,"after inversion: pl=%d pr=%g\n",pl,pr[pl]);
2662  // if(pr[UU]>0.1) dualfprintf(fail_file,"ADEATHUU: ijk=%d %d %d u=%g %g (%g)\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[UU],Ugeomfree[UU],Ugeomfree0[UU]);
2663  // if(fabs(pr[U1])>1.0) dualfprintf(fail_file,"ADEATHU1: ijk=%d %d %d u=%g %g (%g)\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[U1],Ugeomfree[U1],Ugeomfree0[U1]);
2664  // }
2665 
2667  //
2668  // now do other non-fluid inversions
2669  //
2671 
2672  if(EOMRADTYPE!=EOMRADNONE){
2673  if(ENFORCEMHDCONS2RADCONS==1){
2674  // KORAL
2675  // NOTEMARK: u2p_rad() uses pr, which will have updated velocities in case radiation inversion wants to use fluid frame reduction. But need to know if got good solution, so pass that flag to u2p_rad()
2676 
2677  // get MHD state
2678  struct of_state q;
2679  get_state_norad_part1(pr, ptrgeom, &q);
2680  get_state_norad_part2(1, pr, ptrgeom, &q); // where entropy would be computed
2681 
2682  // get accurate UMHD[pmhd] to avoid inversion inaccuracies for MHD inversion part
2683  extern int primtoflux_nonradonly(int needentropy, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
2684  FTYPE uumhd[NPR],uumhdabs[NPR];
2685  PLOOP(pliter,pl) uumhd[pl] = Ugeomfree[pl];
2686  primtoflux_nonradonly(1,pr,&q,TT,ptrgeom, uumhd, uumhdabs); // anything not set is set as zero, which is rad.
2687 
2688  // enforce conservation even if inaccuracy in MHD inversion
2689  int iv;
2690  DLOOPA(iv) uumhd[URAD0+iv] = Ugeomfree[URAD0+iv] - (uumhd[UU+iv]-Ugeomfree[UU+iv]);
2691  PLOOP(pliter,pl) Ugeomfree[pl] = uumhd[pl];
2692 
2693  u2p_rad(showmessages, allowlocalfailurefixandnoreport, GAMMAMAXRAD, whichcap, Ugeomfree,pr,ptrgeom,lpflag,lpflagrad);
2694  //*lpflagrad=0; // test that check_on_inversion triggered where velocity limiter applies
2695 
2696 
2697  get_state_radonly(pr, ptrgeom, &q);
2698 
2699  extern int primtoflux_radonly(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
2700  FTYPE uurad[NPR],uuradabs[NPR];
2701  primtoflux_radonly(pr,&q,TT,ptrgeom, uurad,uuradabs); // all non-rad stuff is set to zero.
2702  // write new uurad's to uu
2703  PLOOP(pliter,pl) if(RADFULLPL(pl)) Ugeomfree[pl]=uurad[pl];
2704  }
2705  else{// required method when pmhd>>prad and small errors in pmhd swamp rad
2706  u2p_rad(showmessages, allowlocalfailurefixandnoreport, GAMMAMAXRAD, whichcap, Ugeomfree,pr,ptrgeom,lpflag,lpflagrad);
2707  }
2708  }
2709 
2710  // if(ptrgeom->i==10 && ptrgeom->k==0){
2711  // PLOOP(pliter,pl) dualfprintf(fail_file,"after rad inversion: pl=%d pr=%g\n",pl,pr[pl]);
2712  // if(pr[UU]>0.1) dualfprintf(fail_file,"BDEATHUU: ijk=%d %d %d u=%g %g (%g)\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[UU],Ugeomfree[UU],Ugeomfree0[UU]);
2713  // if(fabs(pr[U1])>1.0) dualfprintf(fail_file,"BDEATHU1: ijk=%d %d %d u=%g %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,pr[U1],Ugeomfree[U1],Ugeomfree0[U1]);
2714  // }
2715 
2716  return(0);
2717 }
2718 
2719 
2720 
2721 
2723 int Utoprimgen_tryagain(int showmessages, int allowlocalfailurefixandnoreport, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE *Ugeomfree,struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
2724 {
2725  int Utoprimgen_tryagain_substep(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE*Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
2726 
2727  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2728  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM2DFINAL, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2729  // can't trust below really (causes some kind of superslow-down when doing torus problem with MCSTEEP)
2730  // Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM5D1, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2731  // LDZ as normally used generates nan's
2732  // Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIMLDZ, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2733  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM1DFINAL, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2734  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM1DOPT, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2735  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM5D2, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2736  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM2D, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2737  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM1D, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2738 
2739  // don't restore in the end, leave to whatever state inversion leaves it in.
2740 
2741  return(0);
2742 
2743 }
2744 
2745 
2748 int Utoprimgen_tryagain2(int showmessages, int allowlocalfailurefixandnoreport, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE *Ugeomfree,struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
2749 {
2750  int Utoprimgen_tryagain_substep(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE*Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
2751  void convert_U_removerestmassfromuu(int utoprimverison, int removerestmassfromuu, FTYPE *U);
2752  FTYPE Uorig0[NPR],Uorig[NPR];
2753  int pl,pliter;
2754 
2755 
2756  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIMJONNONRELCOMPAT, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2757  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM5D1, eomtype, whichcap, parameter, Ugeomfree0, Ugeomfree, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2758 
2759  PALLLOOP(pl){
2760  Uorig0[pl]=Ugeomfree0[pl];
2761  Uorig[pl]=Ugeomfree[pl];
2762  }
2763  // assume at this point that U is such that setup for REMOVERESTMASSFROMUU==2 so that UU has rest-mass subtracted.
2764  // so need to add it back in for 2D FINAL method
2765  // convert U into form appropriate for inversion routine
2766  convert_U_removerestmassfromuu(UTOPRIM2DFINAL,REMOVERESTMASSFROMUU,Uorig);
2767  convert_U_removerestmassfromuu(UTOPRIM2DFINAL,REMOVERESTMASSFROMUU,Uorig0);
2768  // now in form usable by UTOPRIM2DFINAL
2769  Utoprimgen_tryagain_substep(showmessages, allowlocalfailurefixandnoreport, UTOPRIM2DFINAL, eomtype, whichcap, parameter, Uorig0, Uorig, ptrgeom, lpflag, pr0, pr,pressure,newtonstats,lpflagrad);
2770 
2771 
2772  // don't restore in the end, leave to whatever state inversion leaves it in.
2773 
2774  return(0);
2775 
2776 }
2777 
2778 
2779 
2780 
2781 
2783 int Utoprimgen_tryagain_substep(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree0, FTYPE*Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr0, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad)
2784 {
2785  int pl;
2786  int Utoprimgen_pick(int showmessages, int allowlocalfailurefixandnoreport, int which, int eomtype, int whichcap, int parameter, FTYPE *Ugeomfree, struct of_geom *ptrgeom, PFTYPE *lpflag, FTYPE *pr, FTYPE *pressure, struct of_newtonstats *newtonstats, PFTYPE *lpflagrad);
2787 
2788  // if really a bad failure that don't want / can't handle, then try again
2789  if(
2790  (IFUTOPRIMFAIL(*lpflag))
2791  &&(!((IFUTOPRIMFAILSOFTNOTRHORELATED(*lpflag))&&(STEPOVERNEGU)))
2792  &&(!((*lpflag==UTOPRIMFAILRHONEG)&&(STEPOVERNEGRHO)))
2793  &&(!((*lpflag==UTOPRIMFAILRHOUNEG)&&(STEPOVERNEGRHOU)))
2794  ){
2795  // restore
2796  PALLLOOP(pl){
2797  Ugeomfree[pl]=Ugeomfree0[pl];
2798  pr[pl]=pr0[pl];
2799  }
2800  // try again
2801  MYFUN(Utoprimgen_pick(showmessages, allowlocalfailurefixandnoreport, which,eomtype, whichcap,parameter,Ugeomfree, ptrgeom, lpflag, pr,pressure,newtonstats,lpflagrad),"step_ch.c:Utoprimgen_tryagain_substep()", "Utoprimgen_pick", 1);
2802  }
2803 
2804  return(0);
2805 }
2806 
2807 
2808 
2809 
2812 int Utoprimloop(FTYPE (*U)[NSTORE2][NSTORE3][NPR],FTYPE (*prim)[NSTORE2][NSTORE3][NPR], struct of_newtonstats *newtonstats)
2813 {
2814  struct of_geom geomdontuse;
2815  struct of_geom *ptrgeom=&geomdontuse;
2816  int i,j,k;
2817  int showmessages=1;
2818  int allowlocalfailurefixandnoreport=1;
2819 
2820  ZLOOP{
2821  get_geometry(i, j, k, CENT, ptrgeom);
2822  // invert True U->p
2823  int eomtype=EOMDEFAULT;
2824  FTYPE dissmeasure=-1.0; // then assume always energy since no info here.
2825  int whichcap=CAPTYPEBASIC;
2826  int whichmethod=MODEDEFAULT;
2827  int modprim=0;
2828  int checkoninversiongas=CHECKONINVERSION;
2829  int checkoninversionrad=CHECKONINVERSIONRAD;
2830  MYFUN(Utoprimgen(showmessages, checkoninversiongas, checkoninversionrad, allowlocalfailurefixandnoreport,0,&eomtype,whichcap,whichmethod,modprim,EVOLVEUTOPRIM,UEVOLVE,MAC(U,i,j,k), NULL, ptrgeom, dissmeasure, MAC(prim,i,j,k), MAC(prim,i,j,k),newtonstats),"step_ch.c:advance()", "Utoprimgen", 1);
2831  }
2832  return(0);
2833 }
2834 
2835 
2836 
2838 int primtoUloop(FTYPE (*prim)[NSTORE2][NSTORE3][NPR],FTYPE (*U)[NSTORE2][NSTORE3][NPR])
2839 {
2840  struct of_geom geomdontuse;
2841  struct of_geom *ptrgeom=&geomdontuse;
2842  struct of_state q;
2843  int i,j,k;
2844 
2845  ZLOOP{
2846  MYFUN(get_state(MAC(prim,i,j,k), ptrgeom, &q),"step_ch.c:primtoUloop()", "get_state()", 1);
2847  get_geometry(i, j, k, CENT, ptrgeom);
2848  // forward calculate U(p)
2849  MYFUN(primtoU(UEVOLVE,MAC(prim,i,j,k), &q, ptrgeom, MAC(U,i,j,k), NULL),"step_ch.c:primtoUloop()", "primtoU()", 1);
2850  }
2851  return(0);
2852 }
2853 
2854 
2855 
2857 void filterffde(int i, int j, int k, FTYPE *pr)
2858 {
2859  int pl,pliter;
2860  struct of_geom geomdontuse;
2861  struct of_geom *ptrgeom=&geomdontuse;
2862  FTYPE prout[NPR],prin[NPR];
2863  FTYPE U[NPR];
2864  struct of_state q;
2865  // int Utoprim_ffde(FTYPE *U, struct of_geom *geom, FTYPE *pr) ;
2866  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
2867  int finalstep=0;
2868  int showmessages=1;
2869  int allowlocalfailurefixandnoreport=1;
2870 
2871  // now filter velocity
2872  get_geometry(i,j,k,CENT,ptrgeom);
2873  get_state(pr,ptrgeom,&q);
2874  primtoU(UNOTHING,pr,&q,ptrgeom,U, NULL);
2875 
2876  // Utoprim_ffde(U,ptrgeom,prout); // no need for initial guess since analytic inversion
2877  int eomtype=EOMDEFAULT;
2878  FTYPE dissmeasure=-1.0; // assume energy inversion ok
2879  int whichcap=CAPTYPEBASIC;
2880  int whichmethod=MODEDEFAULT;
2881  int modprim=0;
2882  int checkoninversiongas=CHECKONINVERSION;
2883  int checkoninversionrad=CHECKONINVERSIONRAD;
2884  Utoprimgen(showmessages, checkoninversiongas, checkoninversionrad, allowlocalfailurefixandnoreport, finalstep, &eomtype,whichcap,whichmethod,modprim,EVOLVEUTOPRIM,UNOTHING,U,NULL,ptrgeom,dissmeasure,pr,prout,&newtonstats);
2885 
2886  PALLLOOP(pl) pr[pl]=prout[pl];
2887  // kill densities
2888  pr[RHO]=pr[UU]=0.0;
2889 
2890 
2891 
2892 }
2893 
2894 
2897 int badenergy(struct of_geom *ptrgeom, FTYPE *energypr, FTYPE *entropypr)
2898 {
2899 
2900  // return(BADENERGYMAC(energypr[UU],entropypr[UU]));
2901  // return(BADENERGY2MAC(energypr[UU],entropypr[UU]));
2902 
2903  // energy solution's specific entropy
2904  FTYPE entropy;
2905 
2906  entropy_calc(ptrgeom,energypr,&entropy);
2907  FTYPE Sspecenergy=entropy/energypr[RHO];
2908 
2909  entropy_calc(ptrgeom,entropypr,&entropy);
2910  FTYPE Sspecentropy=entropy/entropypr[RHO];
2911 
2912  if(Sspecenergy>=Sspecentropy) return(0);
2913  else return(1);
2914 
2915 
2916 
2917 }
2918 
2919 
2921 int whetherdoentropy(struct of_geom *ptrgeom, FTYPE fracenergy, int entropynotfail, int energynotfail, int radinvmodentropy, int radinvmodenergy, FTYPE tryerror, FTYPE okerror, FTYPE baderror, FTYPE entropyerror, FTYPE energyerror, FTYPE *entropypr, FTYPE *energypr)
2922 {
2923  int doentropy=0;
2924 
2925  // KORALTODO: radinvmodenergy and radinvmodntropy conditions.
2926  doentropy=
2927  fracenergy==0.0 && entropynotfail==1 ||
2928  // energynotfail==1 && entropynotfail==1 && (fracenergy>0.0 && fracenergy<1.0) && (entropyerror<=okerror && energyerror>okerror) ||
2929  energynotfail==0 && entropynotfail==1 ||
2930  entropynotfail==1 && energynotfail==1 && (entropyerror<tryerror && energyerror>baderror) ||
2931  // entropynotfail==1 && energynotfail==1 && (badenergy(ptrgeom,energypr,entropypr) && (entropyerror<okerror && energyerror>entropyerror)) ||
2932  // entropynotfail==1 && energynotfail==1 && (badenergy(ptrgeom,energypr,entropypr) && (entropyerror<tryerror && energyerror>tryerror)) // switch to entropy if suspicious energy solution that looks approximate but mathematica checks suggest are mostly u_g<0 if accurate solution found.
2933  entropynotfail==1 && energynotfail==1 && (badenergy(ptrgeom,energypr,entropypr) && (entropyerror<okerror && energyerror<okerror)) // switch to entropy if ug for energy is smaller, and can trust both energy and entropy ug so can trust that comparison.
2934  ||entropynotfail==1 && energynotfail==1 && radinvmodenergy>0 && radinvmodentropy<=0 && entropyerror<okerror // avoid energy if it particularly leads to radiation reaching maximum gamma or minimum Erf. Ok to do because if dissipating, that would only normally create more Erf, not less, in optically thin regions where one might worry about switching to entropy.
2935  ;
2936 
2937  // override to preserve better force balance, as long as energy solution is a good one.
2938  // so might use energy even in expanding flows.
2939  if(entropynotfail==1 && energynotfail==1 && radinvmodenergy<=0 && radinvmodentropy>0 && energyerror<okerror){
2940  doentropy=0;
2941  if(debugfail>=3) dualfprintf(fail_file,"Went to energy with errorabs=%g because radinvmodentropy=%d with with entropyerror=%g\n",energyerror,radinvmodentropy,entropyerror);
2942  }
2943  if(entropynotfail==1 && energynotfail==1 && radinvmodenergy>0 && radinvmodentropy<=0 && entropyerror<okerror){
2944  if(debugfail>=3) dualfprintf(fail_file,"Went to entropy with errorabs=%g because radinvmodenergy=%d with with energyerror=%g\n",entropyerror,radinvmodenergy,energyerror);
2945  }
2946 
2947  // UTOPRIMRADFAILCASE2A;
2948  // UTOPRIMRADFAILCASE3A;
2949 
2950  return(doentropy);
2951 
2952 }
2953 
2954 
2956 int set_fracenergy(int i, int j, int k, FTYPE dissmeasure, FTYPE *fracenergy)
2957 {
2958  // get divcond. Go over dimensions in case not full 3D. Just duplicates value as per in flux.c.
2959  const int NxNOT1[NDIM]={0,N1NOT1,N2NOT1,N3NOT1};
2960  int dir;
2961  FTYPE divcond;
2962  FTYPE DIVCONDDN=-BIG,DIVCONDUP=BIG;
2963 
2964 
2966  DIVCONDDN=0.0;
2967  DIMENLOOP(dir){
2968  if(NxNOT1[dir]){
2969  // problems when V small
2970  divcond=GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k);
2971  }
2972  }
2973  }
2975  // DIVCONDDN=-0.01;
2976  // DIVCONDDN=-SMALL;
2977  // DIVCONDDN=-1E-6;
2978  // DIVCONDDN=-1E-3;
2979 
2980  // DIVCONDUP=-1E-6;
2981  // DIVCONDUP=-100.0*NUMEPSILON;
2982 
2983  // DIVCONDDN=-0.1;
2984  // DIVCONDDN=-100.0*NUMEPSILON;
2985  DIVCONDDN=0.0;
2986  DIVCONDUP=DIVCONDDN;
2987 
2988  divcond=dissmeasure;
2989  // if(GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k);
2990  }
2991 
2992 
2993 
2995  //
2996  // then interpolate between energy and entropy solution
2997  // below DIVCONDDN, do only energy
2998  // above DIVCONDUP, do only entropy
2999  //
3001  if(DIVCONDDN!=DIVCONDUP){
3002  *fracenergy = (divcond-DIVCONDUP)/(DIVCONDDN-DIVCONDUP);
3003  *fracenergy=MIN(1.0,*fracenergy);
3004  *fracenergy=MAX(0.0,*fracenergy);
3005  }
3006  else{
3007  // force so no machine error issues in switch
3008  if(divcond<DIVCONDDN) *fracenergy=1.0;
3009  else *fracenergy=0.0;
3010  }
3011 
3012 
3013  // DEBUG
3014  // dualfprintf(fail_file,"divcond=%g fracenergy=%g\n",divcond,fracenergy);
3015 
3016 
3017  return(0);
3018 }
3019 
3020 
3022 int entropyfixguess(struct of_state *q, struct of_geom *ptrgeom, FTYPE *uu, FTYPE *pp)
3023 {
3024  if(ENTROPY>=0 && isfinite(pp[ENTROPY]) && isfinite(uu[ENTROPY]) ){
3025  int pliter,pl;
3026 
3027  struct of_state qlocal;
3028  struct of_state *qptr;
3029 
3030  // guess's entropy
3031  FTYPE entropy0,specificentropy0;
3032  entropy_calc(ptrgeom,pp,&entropy0);
3033  specificentropy0=entropy0/pp[RHO];
3034 
3035  if(q==NULL){
3036  qptr=&qlocal;
3037  get_state_uconucovonly(pp, ptrgeom, qptr);
3038  }
3039  else qptr=q;
3040 
3041  // conserved "initial+flux" estimate of entropy
3042  FTYPE rhoE,entropyE,specificentropyE;
3043  rhoE=fabs(uu[RHO]/qptr->ucon[TT]); // approximate using old u^t
3044  // modify guess for rho
3045  pp[RHO]=MAX(SMALL,MIN(fabs(pp[RHO]),fabs(rhoE))); // start small side to make entropy higher
3046 
3047  specificentropyE=uu[ENTROPY]/uu[RHO]; // no approximation
3048  entropyE=specificentropyE*pp[RHO]; // worse case for entropy (i.e. highest entropy). Approximate entropyE.
3049  // if(specificentropy0<specificentropyE){
3050  FTYPE ppnew[NPR]; PLOOP(pliter,pl) ppnew[pl]=pp[pl];
3051  // no approximation for u_g from entropyE
3052  ufromentropy_calc(ptrgeom, entropyE, ppnew); // LEAKNOTE: valgrind says use of uninit here.
3053  ppnew[UU]=ppnew[ENTROPY];
3054 #define SHOWUGCHANGEDUETOENTROPY (10.0)
3055  if(debugfail>=3 && (fabs(ppnew[UU]/pp[UU])>SHOWUGCHANGEDUETOENTROPY || ppnew[UU]<pp[UU]) ) dualfprintf(fail_file,"CHANGE : Fixed (%g/%g) entropy (%g vs. %g): guessrho=%g guessug=%g newug=%g dug=%g\n",uu[ENTROPY],uu[RHO],specificentropy0,specificentropyE,pp[RHO],pp[UU],ppnew[UU],pp[UU]-ppnew[UU]);
3056  // modify guess for u_g (start higher than actual solution hopefully)
3057  pp[UU]=MAX(pp[UU],ppnew[UU]);
3058 
3059  // recompute uu's so consistent (No, uu=uu is better approximation)
3060  // struct of_state req;
3061  // get_state(pp, ptrgeom, &req);
3062  // primtoU(UNOTHING,pp,&req,ptrgeom, uu, uuabs);
3063  }
3064 
3065  return(0);
3066 }
3067 
3068 
3069 
3071 int setnewtonstatsdefault(struct of_newtonstats *newtonstats)
3072 {
3073 
3074  newtonstats->tryconv=-1.0;
3075  newtonstats->tryconvultrarel=-1.0;
3076  newtonstats->mintryconv=-1.0;
3077  newtonstats->maxiter=-1;
3078  newtonstats->extra_newt_iter=-1;
3079  newtonstats->extra_newt_iter_ultrarel=-1;
3080 
3081  return(0);
3082 }
3083 
3084 
3085 
3086 
3088 int isflowcold(FTYPE COLDFACTOR, int includerad, FTYPE *pb, struct of_geom *ptrgeom, struct of_state *q, FTYPE *uu0)
3089 {
3090  int iscoldflow=0;
3091 
3092  //#define COLDFACTOR (0.5)
3093 
3094  if(includerad==0 || EOMRADTYPE==EOMRADNONE || uu0==NULL){
3095  int jj;
3096  FTYPE usq=0.0; SLOOPA(jj) usq+=q->ucon[jj]*q->ucov[jj];
3097  // FTYPE ucovgas[NDIM];
3098  // DLOOPA(jj) ucovgas[jj]=q->ucov[jj];
3099  // FTYPE ucongas[NDIM];
3100  // DLOOPA(jj) ucongas[jj]=q->ucon[jj];
3101  // FTYPE ugas=0.0; SLOOPA(jj) ugas+=ucovgas[jj]*ucongas[jj];
3102  // u_g << rho u^2
3103  // && fabs(ucongas[TT]*ucovgas[TT])<COLDFACTOR*fabs(ugas)
3104  iscoldflow = (pb[UU]<COLDFACTOR*pb[RHO]); // IE < RE
3105  iscoldflow = (iscoldflow && pb[UU]<COLDFACTOR*(pb[RHO]+pb[UU])*fabs(usq)); // IE < KE
3106  }
3107  else{// RAD
3108  int jj;
3109  FTYPE usq=0.0; SLOOPA(jj) usq+=q->ucon[jj]*q->ucov[jj];
3110  FTYPE ucovgas[NDIM],ucovrad[NDIM];
3111  DLOOPA(jj) ucovgas[jj]=uu0[UU+jj];
3112  DLOOPA(jj) ucovrad[jj]=uu0[URAD0+jj];
3113  FTYPE ucongas[NDIM],uconrad[NDIM];
3114  raise_vec(ucovgas,ptrgeom,ucongas);
3115  raise_vec(ucovrad,ptrgeom,uconrad);
3116  FTYPE ugas=0.0; SLOOPA(jj) ugas+=ucovgas[jj]*ucongas[jj];
3117  FTYPE urad=0.0; SLOOPA(jj) urad+=ucovrad[jj]*uconrad[jj];
3118  // t^t_\mu = T^t_\mu + \rho_0 u^t = uu0[UU+mu] : t^t_t = \rho_0 (1+u_t) u^t + (u_g+p_g) u^t u_t + p_g = uu0[UU]
3119  // R^t_\mu = uu[URAD0+mu]
3120  // u_g < rho u^2 and -u^t u_t < |u| and \gamma_rad^2 < |urad|
3121  // these ensure gas internal energy is small
3122  // u_g < rho u^2 and
3123  iscoldflow = (pb[UU]<COLDFACTOR*pb[RHO]*fabs(usq) && fabs(ucongas[TT]*ucovgas[TT])<COLDFACTOR*fabs(ugas) && fabs(uconrad[TT]*ucovrad[TT])<COLDFACTOR*fabs(urad));
3124  }
3125 
3126 
3127  return(iscoldflow);
3128 }
3129 
3130 int isflowffde(FTYPE FFDEFACTOR, FTYPE *pb, struct of_state *q)
3131 {
3132  int isffdeflow=0;
3133 
3134  //#define FFDEFACTOR (1.0) // assume if here then desparate to avoid failure. 1.0 should be when only order unity errors.
3135 
3136  int jj;
3137  FTYPE usq=0.0; SLOOPA(jj) usq+=q->ucon[jj]*q->ucov[jj];
3138  FTYPE bsq=0.0; DLOOPA(jj) bsq+=q->bcon[jj]*q->bcov[jj];
3139  // u_g << rho u^2
3140  // && fabs(ucongas[TT]*ucovgas[TT])<COLDFACTOR*fabs(ugas)
3141  isffdeflow = (pb[RHO]<FFDEFACTOR*fabs(bsq) && pb[UU]<FFDEFACTOR*fabs(bsq)); // RE<MAGE and IE<MAGE
3142  isffdeflow = (isffdeflow && (pb[RHO]+pb[UU])*fabs(usq) < FFDEFACTOR*fabs(bsq)); // KE<MAGE
3143 
3144 
3145  return(isffdeflow);
3146 }