HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
phys.tools.rad.c
Go to the documentation of this file.
1 // __WORKINGONIT__ indicates what still in development
2 
8 
9 // KORALTODO: B Not setup for iter=0 2 1 0 : 1 2 : 3 13 : 14 200 : 14
10 
11 
12 // KORALTODO:
13 
14 /* 1) Reorder URAD method so: */
15 
16 /* a) URAD */
17 /* b) URAD->PRAD */
18 /* c) Re-get URAD(PRAD) in case floors/ceilings */
19 /* d) Apply relative 4-force condition using this new URAD -> UGAS */
20 /* e) UGAS->PGAS */
21 /* f) Re-get UGAS(PGAS) in case floors/celings/failures/errors/etc. */
22 
23 /* As long as MHD doesn't fail, then even if RAD hits ceilings, the solution will be in relative force balance. -- i.e. total energy-momentum conservation will hold despite change in URAD. */
24 
25 /* Right now, I use pre-corrected URAD to get dUrad -> dUgas, so if rad hits ceilings while gas does not, then relative force balance is lost when could have been maintained. */
26 
27 /* Need to have Utoprimgen() call without doing radiation inversion to save time .. doradonly=-1 ? */
28 
29 
30 
31 
33 
34 
35 
36 // include globals
37 #include "decs.h"
38 
39 
40 
41 
42 struct of_method {
43  int iter; // input
44  int eomtype; // input(can be output)
45  int itermode; // input
46  int baseitermethod; // input
47  FTYPE fracenergy; // input
48  FTYPE dissmeasure; // input
49 
50  // outsputs
60 };
61 
62 struct of_refU {
63  // inputs
66 
67  // outputs
68  int numdims; // not used yet
69  int startjac;
70  int endjac;
71  int irefU[NDIM];
72  int iotherU[NDIM];
73  int erefU[NDIM];
74  int eotherU[NDIM];
79 };
80 
81 
82 
83 
85 //
86 // BEGIN: f2c stuff for Ramesh's solver code in fortran
87 //
89 
91 #include "f2c.h"
92 
93 #ifdef KR_headers
94 double d_sign(aa,bb) doublereal *aa, *bb;
95 #else
96 double d_sign(doublereal *aa, doublereal *bb)
97 #endif
98 {
99 double x;
100 x = (*aa >= 0 ? *aa : - *aa);
101 return( *bb >= 0 ? x : -x);
102 }
103 
104 #ifdef KR_headers
105 //double floor();
107 #else
108  //#undef abs
109  //#include "math.h"
111 #endif
112 {
113 return( (*x)>=0 ?
114  floor(*x + .5) : -floor(.5 - *x) );
115 }
116 
117 #define MYEXTERN extern
118 
119 #ifdef KR_headers
120 extern void f_exit();
121 int s_stop(s, n) char *s; ftnlen n;
122 #else
123 #undef abs
124 #undef min
125 #undef max
126 #include "stdlib.h"
127 #ifdef __cplusplus
128 MYEXTERN "C" {
129 #endif
130 #ifdef __cplusplus
131 MYEXTERN "C" {
132 #endif
133 void f_exit(void);
134 
135 int s_stop(char *s, ftnlen n)
136 #endif
137 {
138 int i;
139 
140 if(n > 0)
141  {
142  fprintf(stderr, "STOP ");
143  for(i = 0; i<n ; ++i)
144  putc(*s++, stderr);
145  fprintf(stderr, " statement executed\n");
146  }
147 #ifdef NO_ONEXIT
148 f_exit();
149 #endif
150 exit(0);
151 
152 /* We cannot avoid (useless) compiler diagnostics here: */
153 /* some compilers complain if there is no return statement, */
154 /* and others complain that this one cannot be reached. */
155 
156 return 0; /* NOT REACHED */
157 }
158 #ifdef __cplusplus
159 }
160 #endif
161 #ifdef __cplusplus
162 }
163 #endif
164 
165 // pow_dd()
166 #ifdef KR_headers
167 double pow();
168 double pow_dd(ap, bp) doublereal *ap, *bp;
169 #else
170 #undef abs
171 #include "math.h"
172 #ifdef __cplusplus
173 MYEXTERN "C" {
174 #endif
175 double pow_dd(doublereal *ap, doublereal *bp)
176 #endif
177 {
178 return(pow(*ap, *bp) );
179 }
180 #ifdef __cplusplus
181 }
182 #endif
183 
184 
185 #include "testfpp.P"
186 // not linking with libf2c since don't want that dependence and conversion doesn't need it since the original code was simple
187 
188 int get_rameshsolution(int whichcall, int radinvmod, int failtype, long long int failnum, int gotfirstnofail, int eomtypelocal, int itermode, int baseitermethod, FTYPE *errorabs, FTYPE *errorabsbestexternal, int iters, int totaliters, FTYPE realdt, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *pb, FTYPE *piin, FTYPE *uu0, FTYPE *uu, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_state *q, FTYPE *ppeng, FTYPE *ppent, FTYPE *uueng, FTYPE *uuent, struct of_state *qeng, struct of_state *qent, int *failtypeeng, FTYPE *errorabseng, int *iterseng, int *radinvmodeng, int *failtypeent, FTYPE *errorabsent, int *itersent, int *radinvmodent);
189 
190 int get_rameshsolution_wrapper(int whichcall, int eomtype, FTYPE *errorabs, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, struct of_state *q, FTYPE *ppeng, FTYPE *ppent, FTYPE *uueng, FTYPE *uuent, FTYPE (*dUcompeng)[NPR], FTYPE (*dUcompent)[NPR], struct of_state *qeng, struct of_state *qent, int *failtypeeng, FTYPE *errorabseng, int *iterseng, int *radinvmodeng, int *failtypeent, FTYPE *errorabsent, int *itersent, int *radinvmodent);
191 
193 //
194 // END: f2c stuff for Ramesh's solver code in fortran
195 //
197 
198 
199 #define PLOOPDYNAMICAL(pliter,pl) PLOOP(pliter,pl) if(SCALARPL(pl)==0)
200 
201 
203 //
204 // Local options (used to be in global.nondepmnemonics.rad.h)
205 //
207 
208 #define AVOIDTAUFORFLOOR (1) // whether to apply optical depth calculation for floor (0) or not (1)
209 
210 
211 #define COURRADEXPLICIT (0.1) // Effective Courant-like factor for stiff explicit radiation source term. Required to not only avoid failure of explicit scheme, but also that explicit scheme is really accurate compared to implicit. E.g., near \tau\sim 1, explicit won't fail with RADPULSEPLANAR but will not give same results as implicit. So only use explicit if really in optically thin regime.
212 
213 
215 #define IMPTRYCONVHIGHTAU (NUMEPSILON*5.0) // for used implicit solver
216 
218 #if(DOPERF)
219 #define IMPTRYCONV (1.e-9) // less greedy so doesn't slow things down so much.
220 #else
221 #define IMPTRYCONV (1.e-12) // works generally to avoid high iterations
222 #endif
223 #define IMPTRYCONVQUICK (1.e-6) // even less greedy so doesn't slow things down so much.
224 
225 #if(DOPERF)
226 #define ITERATIONMARGINAL2 (4)
227 #define IMPTRYCONVMARGINAL2 (1.e-5) // even less greedy so doesn't slow things down so much.
228 #else
229 #define ITERATIONMARGINAL2 (4)
230 #define IMPTRYCONVMARGINAL2 (1.e-6) // even less greedy so doesn't slow things down so much.
231 #endif
232 
233 #define IMPTRYCONVMARGINAL (1.e-6) // even less greedy so doesn't slow things down so much.
234 
235 #define IMPTRYCONVSUPERQUICK (1.e-3) // even less greedy so doesn't slow things down so much.
236 
237 #define IMPTRYCONVABS ((FTYPE)(NDIM+2)*trueimptryconv)
238 
240 //#define IMPOKCONVCONST (1E-9)
241 
244 // ensure energy conservation equation used as much as possible
245 //#define IMPALLOWCONVCONST (1.e-7)
246 //#define IMPALLOWCONVCONST (1.e-6)
247 //#define IMPALLOWCONVCONST (1.e-5)
248 #if(DOPERF)
249 #define IMPALLOWCONVCONST (1.e-3)
250 #define IMPOKCONVCONST (1E-4) // even more likely to use energy solution
251 #else
252 #define IMPALLOWCONVCONST (1.e-5)
253 #define IMPOKCONVCONST (1E-6) // even more likely to use energy solution
254 #endif
255 
256 
257 #define IMPOKCONVCONSTABS ((FTYPE)(NDIM+2)*IMPOKCONVCONST)
258 #define IMPOKCONV (MAX(trueimptryconv,IMPOKCONVCONST))
259 #define IMPOKCONVABS ((FTYPE)(NDIM+2)*IMPOKCONV)
260 
261 
262 #define IMPALLOWCONVCONSTABS ((FTYPE)(NDIM+2)*IMPALLOWCONVCONST)
263 //#define IMPALLOWCONV (MAX(trueimptryconv,IMPALLOWCONVCONST))
264 #define IMPALLOWCONV (trueimpallowconv)
265 #define IMPALLOWCONV2 (IMPALLOWCONV)
266 #define IMPALLOWCONVABS ((FTYPE)(NDIM+2)*IMPALLOWCONV)
267 
269 //#define IMPBADENERGY (MIN(IMPALLOWCONV,1E-7))
270 #define IMPBADENERGY (MIN(IMPALLOWCONV,1E-6))
271 
272 // what optical depth in a cell to say below which can use allowed tolerance, to speed things up.
273 #define TAUTOTMAXHIGHERTOL (-1.0) // i.e. avoid this
274 #define IMPTRYCONV_TAUTOTMAXHIGHERTOL (1E-4)
275 
276 // tolerances tried and allowed based upon position (sometimes commented out in _mode() function)
277 #define IMPTRYCONV_RHORHIGHERTOL (1E-3) // (leads to transition)
278 #define IMPTRYCONV_ROUTERHIGHERTOL (1E-3) // good to have since don't care about outer region with OUTERDEATH
279 #define IMPALLOWCONV_RHORHIGHERTOL (1E-2) // allow lower tol inside horizon to avoid failures (but leads to transition) NOTEMARK: Probably don't want this >1/BSQORHOLIMIT else rho will be in error by more than order unity just from G, which may be limit of acceptability. u will be in error much more likely, but u driven by Comptonization often so by thermal equilibrium.
280 
281 
283 #define ITERMHDINVTRYHARDER 5
284 #define MINTRYCONVFORMHDINVERSION (1E-4) // assume not failure if got down to this much. -- don't have to be related to implicit allowance.
285 
286 
288 #define ABORTBACKUPIFNOERRORREDUCE 1
289 #define IMPTRYCONVALT (MAX(1E-8,IMPTRYCONVABS)) // say that if error isn't reducing, ok to abort with this error. Only time saver, but realistic about likelihood of getting smaller error.
290 
292 #define IMPTRYDAMPCONV (5.0*IMPTRYCONVABS)
293 
295 
296 
297 
304 #if(REALTYPE==FLOATTYPE)
305 #define IMPEPSLARGE (1E-4) // on small side
306 #define IMPEPSSMALL (1E-4) // on small side
307 #define ERRORFORIMPEPSSMALL (1E-5)
308 #elif(REALTYPE==DOUBLETYPE)
309 #define IMPEPSLARGE (1E-8) // Was 1E-6 (see next line)
310 #define IMPEPSSMALL (1E-10) // Was 1E-7 (but with PMHD method and disk-jet problem, led to very often not getting solution. Not sure why)
311 //#define IMPEPSSMALL (1E-8)
312 #define ERRORFORIMPEPSSMALL (1E-9)
313 #elif(REALTYPE==LONGDOUBLETYPE)
314 #define IMPEPSLARGE (1E-8)
315 #define IMPEPSSMALL (1E-10)
316 #define ERRORFORIMPEPSSMALL (1E-9)
317 #endif
318 
319 
320 // whether to skip computing Jacobian every step after certain condition of having done a few steps and then compute every few steps only.
321 #define SKIPJACCOMPUTE (DOPERF)
322 #define SKIPJACITER (4)
323 #define SKIPJACFACTOR (4)
324 
325 
326 
328 #define MAXIMPEPS (0.3)
329 
331 #define MAXJACITER (10)
332 
333 
334 
335 //#define IMPMAXITER (15) // for used implicit solver // For others
336 #define IMPMAXITERLONG (100) // for used implicit solver
337 #define IMPMAXITERMEDIUM (40)
338 #define IMPMAXITERQUICK (13)
339 #define IMPMAXITERSUPERQUICK (2)
340 
341 #define IMPMINABSERROR (1E-100) // minimum absolute error (or value) below which don't treat as bad error and just avoid 4-force. Otherwise will "fail" implicit solver even if impossible to reach smaller relative error due to absolute machine precision issues.
342 
349 #define IMPLICITERRORNORM 4
350 
351 
352 #define MAXSUBCYCLES (2000) // for explicit sub-cycles when doing reversion
353 
355 #define MAXSUBCYCLESFAIL (MAXSUBCYCLES*100)
356 
357 
358 #define MAXF1TRIES 20 // 20 might sound like alot, but Jacobian does 4 to 5 inversions each iteration, and that amount is only typically needed for very first iteration.
359  // goes to f1iter=10 for RADPULSE KAPPAES=1E3 case. Might want to scale maximum iterations with \tau, although doubling of damping means exponential w.r.t. f1iter, so probably 50 is certainly enough since 2^(-50) is beyond machine precision for doubles.
360 
361 #define MAXMHDSTEPS (trueimpmaxiter*6) // limit total number of MHD inversion steps
362 
363 
364 #define RADDAMPDELTA (0.5) // choose, but best to choose 1/Integer so no machine precision issues.
365 #define RADDAMPUNDELTA (1.0/RADDAMPDELTA)
366 
367 // whether to try explicit first before implicit steps
368 #define TRYFIRSTEXPLICIT 1
369 
370 // whether to try normal guess if explicit fails as guess
371 // helps avoid some failures due to guess issue
372 // slows the code down some, and if consistent failure in a cell (say equator near inner radial boundary), then will slow down entire run by about a factor of two. So only use with DOPERF==0 for now, and assume fixups will be efficient enough.
373 #define DONONEXPLICITIFFAILS ((DOPERF==0)*TRYFIRSTEXPLICIT)
374 
375 
376 
377 #define TAUFAILLIMIT (2.0/3.0) // at what \tau below which to assume "failure1" in u2p_rad() means should be moving at gammamax rather than not moving.
378 
379 #define TAUSWITCHPBVSPIIN (2.0/3.0) // at what \tau to switch using pb(uu0) vs. piin(Uiin).
380 
381 
383 #define IMPLICITREVERTEXPLICIT 0 // problem. Not a good idea. -- should try implicit again, starting out with more damping.
384 
386 #define MAXEXPLICITSUBSTEPCHANGE 1.e-2
387 
393 #define TAUSUPPRESS 0 // makes physical sense, but might be wrong in some limits (i.e. Gd can still be large relative), but try to account for lambda as well.
394 #define SPACETIMESUBSPLITNONE 1 // DON'T USE! (gets inversion failures because overly aggressive)
395 #define SPACETIMESUBSPLITTIME 2 // probably not ok -- need to split off mhd and rad
396 #define SPACETIMESUBSPLITALL 3 // probably not ok -- need to split off mhd and rad
397 #define SPACETIMESUBSPLITSUPERALL 4 // OK TO USE sometimes, but not always
398 #define SPACETIMESUBSPLITMHDRAD 5 // KINDA OK TO USE (generates noise in velocity where E is very small, but maybe ok since sub-dominant and don't care about velocity where E is small. E evolves fine, but Rtx eventually shows issues.)
399 #define SPACETIMESUBSPLITTIMEMHDRAD 6 // OK TO USE sometimes (works fine and no noise in velocity because split it off. Might have trouble in multiple dimensions if sub-dominant momentum dimension requires implicit step -- but general diffusive would suggest unlikely. But, not efficient in optically thick regime once radiation velocity is non-trivial in magnitude)
400 
401 #define WHICHSPACETIMESUBSPLIT TAUSUPPRESS // only tausuppress works in general.
402 
405 #define NUMERRORTYPES 2 // 0: over iterated 1: over all relevant terms
406 #define WHICHERROR 1 // choose, but generally should be 1.
407 
408 
409 //SPACETIMESUBSPLITTIMEMHDRAD // TAUSUPPRESS
410 // SPACETIMESUBSPLITTIMEMHDRAD // SPACETIMESUBSPLITMHDRAD // SPACETIMESUBSPLITSUPERALL // TAUSUPPRESS
411 
417 //#define GETRADINVFROMUU0FORPB 3 // makes use more ITERMODESTAGES
418 #define GETRADINVFROMUU0FORPB 1 // might be expensive if uu0 has no solution for the MHD inversion.
419 
426 #define USEDUINRADUPDATE 1
427 
430 #define USEINPUTASGUESSIFERRORSMALL (WHICHERROR==1)
431 
432 
433 #define GAMMASMALLLIMIT (1.0-1E-10) // at what point above which assume gamma^2=1.0
434 
435 
437 #define JONCHOICE 0
438 #define OLEKCHOICE 1
439 
440 #define CASECHOICE JONCHOICE // choose
441 //#define CASECHOICE OLEKCHOICE // choose
442 
443 #define TOZAMOFRAME 0 // reduce to ZAMO gammarel=1 frame (e.g. in non-GR that would be grid frame or v=0 frame or gammarel=1).
444 #define TOFLUIDFRAME 1 // reduce to using fluid frame (probably more reasonable in general).
445 #define TOOPACITYDEPENDENTFRAME 2
446 
447 #define M1REDUCE TOOPACITYDEPENDENTFRAME // choose
448 
449 // KORALTODO: The below need to be chosen intelligently
450 
453 #define MINTAUSOURCE (NUMEPSILON)
454 
455 
456 
458 //
459 // START SOME LOCAL OPTIONS
460 //
462 
466 #define DOSUBJAC 1
467 #define ENERGYSIMPLEFACTOR (NDIM) // NDIM=4 times simpler than full step
468 
469 
470 #define ITERMODENORMAL 0
471 #define ITERMODESTAGES 1
472 #define ITERMODECOLD 2
473 
474 
477 #define BEGINMOMSTEPS0 1
478 #define ENDMOMSTEPS0 2
479 
480 #define BEGINENERGYSTEPS0 3
481 #define ENDENERGYSTEPS0 13
482 
483 #define BEGINFULLSTEPS0 14
484 #define ENDFULLSTEPS0 (IMPMAXITERLONG*2)
485 
486 #define BEGINNORMALSTEPS0 BEGINFULLSTEPS0
487 
488 
489 
490 
492 #define NUMPRIORERRORSITER0 7
493 #define NUMPRIORERRORS 5
494 #define PRIORERRORCHANGEREQUIRED (0.5) // damping is included below when used
495 
497 #define DEBUGMAXITER (PRODUCTION==0)
498 
501 #define DEBUGMAXITERVELOCITY 1
502 
503 #define DEBUGLEVELIMPSOLVER 3 // which debugfail>=# to use for some common debug stuff
504 //#define DEBUGLEVELIMPSOLVER 2 // which debugfail>=# to use for some common debug stuff
505 
506 #define DEBUGLEVELIMPSOLVERMORE 3 // which debugfail>=# to use for some common debug stuff
507 //#define DEBUGLEVELIMPSOLVERMORE 2 // which debugfail>=# to use for some common debug stuff
508 
510 #define RAMESHFIXEARLYSTEPS (DOSUBJAC==1 ? 0 : 3) // 3 if used is default
511 
513 #define JONHOLDPOS 1
514 
515 #define NEWJONHOLDPOS 0 // __WORKINGONIT__: WORKING ON IT
516 
518 #define NUMHOLDTIMES 6
519 
520 
522 #define RAMESHSTOPENERGYIFTOOOFTENBELOWENTROPY 3
523 
526 // Also, have found switching during iterations can lead to solution going astray
527 // But still currently allow Utoprimgen() to do MHD inversion of any backup, just that once out of Utoprimgen() we treat as original starting eomtype and eomtype is not changed.
528 //#define SWITCHTOENTROPYIFCHANGESTOENTROPY (mtd->implicitferr==QTYUMHD ? 0 : 1)
529 #define SWITCHTOENTROPYIFCHANGESTOENTROPY (0)
530 
531 
532 
534 #define USERAMESH 0 // too slow if used too often, and rarely result really used.
535 
537 #define TRYHARDERFEEDGUESSTOL (1E-4)
538 
540 #define ERRORTOUSEENTROPYFORENERGYGUESS (1E-4)
541 
542 
544 #define GETBEST 1
545 
546 
548 #define DOFINALCHECK 1
549 
550 
552 #define REPORTMAXITERALLOWED (PRODUCTION==0)
553 
555 #define FORCEJDIFFNOCROSS 1
556 
560 #define POSTNEWTONCONVCHECK 1
561 
563 #define DIFFXLIMIT (10.0*NUMEPSILON)
564 
565 #define LOCALPREIMPCONVX (10.0*NUMEPSILON)
566 #define LOCALPREIMPCONVXABS ((FTYPE)(NDIM+2)*LOCALPREIMPCONVX)
567 
568 
570 #define NUMNOERRORREDUCE0 (5 + mtd.BEGINNORMALSTEPS)
571 #define NUMNOERRORREDUCE 5
572 
573 
576 #define SWITCHTODONOTHING 1
577 
579 #define CHANGEDAMPFACTOR 2 // bit risky to set to 1 since changing DAMPFACTOR for no good reason limits ability to converge at normal rate.
580 #define NUMDAMPATTEMPTS (3*((DOPERF)==0) + 1*((DOPERF)==1))
581 
582 #define NUMDAMPATTEMPTSQUICK 1
583 
584 
586 #define FACTORBADJUMPERROR (1.0E2)
587 
588 
591 #define WHICHU2PRAD 1
592 
594 //#define GAMMAMAXRADIMPLICITSOLVER (1E5)
595 #define GAMMAMAXRADIMPLICITSOLVER (GAMMAMAXRAD) // for radiation, seek actual solution with this limit. Solver can find solutions, while harder when limiting gamma_{gas} for some reason.
596 
597 
599 #define ENTROPYOPT 1
600 
602 #define ALLOWUSEUUALT 0
603 
605 #define USECAPTYPEFIX2FORF1 1
606 
607 #define USECAPTYPEFIX2FORFINALCHECK 1
608 
609 #define AVOIDURAD0IFRADINVMODANDPMHDMETHOD (USECAPTYPEFIX2FORF1!=0)
610 
611 #define TREATRADINVCAPASNONFAILUREFORPMHDMETHOD (USECAPTYPEFIX2FORF1!=0)
612 
614 #define LETPMHDFAIL 1
615 
617 #define USEPRIORITERMETHOD 0
618 
620 #define STOPIFVERYLOWERROR (1)
621 
622 #define STOPIFITERLOWERROR (0)
623 
624 
625 
626 
627 
628 
629 
630 
631 
632 #define FAILRETURNGOTRIVIALEXPLICIT -1
633 #define FAILRETURNNOFAIL 0
634 #define FAILRETURNGENERAL 1
635 #define FAILRETURNJACISSUE 2
636 #define FAILRETURNMODESWITCH 3
637 #define FAILRETURNNOTTOLERROR 4
638 
639 #define ACCEPTASNOFAILURE(failreturn) (failreturn==FAILRETURNNOFAIL || failreturn==FAILRETURNNOTTOLERROR || failreturn==FAILRETURNGOTRIVIALEXPLICIT)
640 //#define GOODNOFAILURE(failreturn) (failreturn==FAILRETURNNOFAIL || failreturn==FAILRETURNGOTRIVIALEXPLICIT)
641 #define NOTACTUALFAILURE(failreturn) (failreturn==FAILRETURNNOFAIL || failreturn==FAILRETURNMODESWITCH || failreturn==FAILRETURNGOTRIVIALEXPLICIT)
642 #define NOTBADFAILURE(failreturn) (failreturn==FAILRETURNNOFAIL || failreturn==FAILRETURNMODESWITCH || failreturn==FAILRETURNNOTTOLERROR || failreturn==FAILRETURNGOTRIVIALEXPLICIT)
643 
644 #define ACTUALHARDFAILURE(failreturn) (failreturn==FAILRETURNGENERAL || failreturn==FAILRETURNJACISSUE)
645 #define ACTUALHARDORSOFTFAILURE(failreturn) (failreturn==FAILRETURNGENERAL || failreturn==FAILRETURNJACISSUE || failreturn==FAILRETURNNOTTOLERROR)
646 #define SWITCHGOODIDEAFAILURE(failreturn) (failreturn==FAILRETURNGENERAL || failreturn==FAILRETURNJACISSUE || failreturn==FAILRETURNNOTTOLERROR || failreturn==FAILRETURNMODESWITCH)
647 
648 
649 
651 // NOTEMARK: for MODEENERGY type method, note that ener.out and jrdpradener (SM) can be used to track all conserved quantities for: 1) how well we have tracked all changes 2) how much each term contributes (fl tracks any changes that deviate unew from pf as well as standard floors)
652 //
653 // Sources of non-conservation *included* in "fl" term: 1) any floors 2) when no implicit solution and reverts to averaging surrounding cells in fixup_utoprim(), because applied to primitives before diag checks ucons vs. pf 3) when OUTERDEATH or POLEDEATH are applied, because comparison between ucons and pf occurs after boundary conditions are applied 4) when implicit solver reverts to having to use entropy, but ends up not able to borrow to conserve total energy, because dUrad forced to always be -dUgas regardles of primitive solution used. 5) when energy (or entropy with borrow) is used, but despite gas having good solution, still radinvmod=1 is triggered so that caps are put in place and total energy conservation not possible -- Because dUrad forced to be -dUgas.
654 
655 // Do the above regarding entropy because will be tracked and for adding to ucum, if sub-step, then might recover.
656 
657 // Sources of non-conservation (e.g. of energy) that are *not* tracked include 1) machine error in doubles adding up over entire grid. 2) fluxes adding up over time 3) u obtained from pf uses get_state and primtoU that has non-trivial errors sometimes, so u cumulated over time won't be perfectly matching fluxes. Still good to know because this is true error because initial U in advance does this exact get_state and primtoU.
658 //
659 // NOTEMARK: u7 associated with conserved B3 that in SPC B^\phi would be conserved if ideal MHD, but dissipation of the B3-supporting currents can mean a non-zero net B3 can change without ever passing through boundaries.
660 //
662 
663 
666 #if(DOPERF)
667 #define MODEMETHOD MODEPICKBESTSIMPLE // switches with only PMHD method
668 #else
669 #define MODEMETHOD MODEPICKBEST // general switching method
670 #endif
671 
672 //#define MODEMETHOD MODEPICKBEST // general switching method
673 //#define MODEMETHOD MODEPICKBESTSIMPLE // switches with only PMHD method // NOTEFORFAST
674 //#define MODEMETHOD MODEPICKBESTSIMPLE2 // switches with all methods but no ITERMODESTAGES attempted
675 //#define MODEMETHOD MODESWITCH
676 //#define MODEMETHOD MODEENERGY
677 //#define MODEMETHOD MODEENTROPY
678 //#define MODEMETHOD MODEENERGYRAMESH
679 
680 
682 //
683 // END SOME LOCAL OPTIONS
684 //
686 
687 
688 
689 
690 
691 
693 static int koral_source_rad_implicit(int *eomtype, FTYPE *pb, FTYPE *pf, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE dissmeasure, FTYPE *dUother ,FTYPE (*dUcomp)[NPR]);
694 
695 static int koral_source_rad_implicit_mode(int modemethodlocal, int allowbaseitermethodswitch, int modprim, int havebackup, int didentropyalready, int *eomtype, int whichcap, int itermode, int *baseitermethod, FTYPE trueimptryconv, FTYPE trueimpokconv, FTYPE trueimpallowconv, int trueimpmaxiter, int truenumdampattempts, FTYPE fracenergy, FTYPE dissmeasure, int *radinvmod, FTYPE *pb, FTYPE *uub, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE *dUother ,FTYPE (*dUcomp)[NPR], FTYPE *errorabs, FTYPE *errorabsbestexternal, int *iters, int *f1iters, int *nummhdinvs, int *nummhdsteps);
696 
697 static int f_implicit(int allowbaseitermethodswitch, int iter, int f1iter, int failreturnallowable, int whichcall, FTYPE impeps, int showmessages, int showmessagesheavy, int allowlocalfailurefixandnoreport, int *eomtype, int whichcap, int itermode, int *baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, int *radinvmod, FTYPE conv, FTYPE convabs, FTYPE allowconvabs, int maxiter, FTYPE realdt, int dimtypef, FTYPE *dimfactU, FTYPE *ppprev, FTYPE *pp, FTYPE *piin, FTYPE *uuprev, FTYPE *Uiin, FTYPE *uu0,FTYPE *uu,FTYPE localdt, struct of_geom *ptrgeom, struct of_state *q, FTYPE *f, FTYPE *fnorm, FTYPE *freport, int *goexplicit, FTYPE *errorabs, FTYPE *errorallabs, int whicherror, int *convreturn, int *nummhdinvsreturn, FTYPE *tautotmaxreturn, struct of_method *mtd, struct of_refU *ru);
698 
699 
700 static int calc_tautot_chieff(FTYPE *pp, FTYPE chi, struct of_geom *ptrgeom, struct of_state *q, FTYPE *tautot, FTYPE *tautotmax);
701 
702 static FTYPE calc_approx_ratchangeRtt(struct of_state *q, FTYPE chieff, FTYPE realdt);
703 
704 
705 static int get_implicit_iJ(int allowbaseitermethodswitch, int failreturnallowableuse, int showmessages, int showmessagesheavy, int allowlocalfailurefixandnoreport, int *eomtypelocal, int whichcap, int itermode, int *baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, FTYPE impepsjac, FTYPE trueimptryconv, FTYPE trueimptryconvabs, FTYPE trueimpallowconvabs, int trueimpmaxiter, int iter, FTYPE errorabs, FTYPE errorallabs, int whicherror, int dimtypef, FTYPE *dimfactU, FTYPE *Uiin, FTYPE *uu, FTYPE *uup, FTYPE *uu0, FTYPE *piin, FTYPE *pp, FTYPE *ppp, FTYPE fracdtG, FTYPE realdt, struct of_geom *ptrgeom, struct of_state *q, FTYPE *f1, FTYPE *f1norm, FTYPE (*iJ)[NPR], int *nummhdinvsreturn, struct of_method *mtd, struct of_refU *ru);
706 
707 static int inverse_33matrix(int sj, int ej, FTYPE aa[][NDIM], FTYPE ia[][NDIM]);
708 static int inverse_11matrix(int sj, int ej, FTYPE aa[][NDIM], FTYPE ia[][NDIM]);
709 
710 
711 static int f_error_check(int showmessages, int showmessagesheavy, int iter, FTYPE conv, FTYPE convabs, FTYPE realdt, int dimtypef, int eomtype, int radinvmod, int itermode, int baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, FTYPE *dimfactU, FTYPE *pp, FTYPE *piin, FTYPE *f1, FTYPE *f1norm, FTYPE *f1report, FTYPE *Uiin, FTYPE *uu0, FTYPE *uu, struct of_geom *ptrgeom, FTYPE *errorabs, FTYPE *errorallabs, int whicherror, struct of_method *mtd, struct of_refU *ru);
712 
713 static int compute_ZAMORAD(FTYPE *uu, struct of_geom *ptrgeom, FTYPE *Er, FTYPE *Utildesq, FTYPE *Utildecon);
714 
715 
716 static int Utoprimgen_failwrapper(int doradonly, int *radinvmod, int showmessages, int checkoninversiongas, int checkoninversionrad, int allowlocalfailurefixandnoreport, int finalstep, int *eomtype, int whichcap, int evolvetype, int inputtype,FTYPE *U, struct of_state *qptr, struct of_geom *ptrgeom, FTYPE dissmeasure, FTYPE *pr, struct of_newtonstats *newtonstats);
717 
718 static void define_method(int iter, int *eomtype, int itermode, int baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, struct of_method *mtd);
719 static void get_refUs(struct of_method *mtd, struct of_refU *ru);
720 
721 #define MAXJACDIM (NDIM)
722 //#define MAXJACDIM (NDIM+1)
723 
724 // debug stuff
725 static void showdebuglist(int debugiter, FTYPE (*pppreholdlist)[NPR],FTYPE (*ppposholdlist)[NPR],FTYPE (*f1reportlist)[NPR],FTYPE (*f1list)[NPR],FTYPE *errorabsf1list,FTYPE *errorallabsf1list, int *realiterlist, FTYPE (*jaclist)[MAXJACDIM][MAXJACDIM], FTYPE *fracdamplist, int *implicititerlist, int *implicitferrlist);
726 int mathematica_report_check(int radinvmod, int failtype, long long int failnum, int gotfirstnofail, int eomtypelocal, int itermode, int baseitermethod, 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, FTYPE *CUimp, struct of_state *q, FTYPE *dUother);
727 
728 // explicit stuff (uses CUf instead of CUf since even with sub-cycling not implicit)
729 static void get_dtsub(int method, FTYPE *pr, struct of_state *q, FTYPE *Ui, FTYPE *Uf, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gdpl, FTYPE chi, FTYPE *Gdplabs, struct of_geom *ptrgeom, FTYPE *dtsub);
730 static void koral_source_dtsub_rad_calc(int method, FTYPE *pr, FTYPE *Ui, FTYPE *Uf, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gdpl, struct of_geom *ptrgeom, FTYPE *dtsub);
731 static int source_explicit(int whichsc, int whichradsourcemethod, int methoddtsub,int *eomtype,
732  void (*sourcefunc)(int method, FTYPE *pr, FTYPE *Ui, FTYPE *Uf, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gpl, struct of_geom *ptrgeom, FTYPE *dtsub),
733  FTYPE *pb, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE *dUother, FTYPE (*dUcomp)[NPR]);
734 
735 // RAD inversion stuff
736 static int get_m1closure_gammarel2_old(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn);
737 static int get_m1closure_gammarel2(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn);
738 
739 static int get_m1closure_gammarel2_cold_old(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn, FTYPE *Erfreturn, FTYPE *urfconrel);
740 static int get_m1closure_gammarel2_cold(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn, FTYPE *Erfreturn, FTYPE *urfconrel);
741 
742 static int get_m1closure_Erf(struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE gammarel2, FTYPE *Erfreturn);
743 
744 static int get_m1closure_urfconrel_old(int showmessages, int allowlocalfailurefixandnoreport, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *Avcon, FTYPE *Avcov, FTYPE gammarel2, FTYPE delta, FTYPE numerator, FTYPE divisor, FTYPE *Erfreturn, FTYPE *urfconrel, PFTYPE *lpflag, PFTYPE *lpflagrad);
745 static int get_m1closure_urfconrel(int showmessages, int allowlocalfailurefixandnoreport, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *Avcon, FTYPE *Avcov, FTYPE gammarel2, FTYPE delta, FTYPE numerator, FTYPE divisor, FTYPE *Erfreturn, FTYPE *urfconrel, PFTYPE *lpflag, PFTYPE *lpflagrad);
746 static int get_m1closure_urfconrel_olek(int showmessages, int allowlocalfailurefixandnoreport, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *Avcon, FTYPE *Avcov, FTYPE gammarel2, FTYPE delta, FTYPE *Erfreturn, FTYPE *urfconrel, PFTYPE *lpflag, PFTYPE *lpflagrad);
747 
748 static int opacity_interpolated_urfconrel(FTYPE tautotmax, FTYPE *pp,struct of_geom *ptrgeom,FTYPE *Avcon, FTYPE Erf,FTYPE gammarel2,FTYPE *Erfnew, FTYPE *urfconrel);
749 
750 // general stuff
751 static FTYPE compute_dt(int isexplicit, FTYPE *CUf, FTYPE *CUimp, FTYPE dtin);
752 
753 static void calc_Gd(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q ,FTYPE *G, FTYPE *Tgasreturn, FTYPE *Tradreturn, FTYPE *chieffreturn, FTYPE *ndotffreturn, FTYPE *ndotffabsreturn, FTYPE *Gabs);
754 static void calc_Gu(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q ,FTYPE *Gu, FTYPE *Tgasreturn, FTYPE *Tradreturn, FTYPE* chieffreturn, FTYPE *ndotffreturn, FTYPE *ndotffabsreturn, FTYPE *Gabs);
755 static int simplefast_rad(int dir, struct of_geom *geom,struct of_state *q, FTYPE vrad2,FTYPE *vmin, FTYPE *vmax);
756 
757 
758 static void calcfull_Trad(FTYPE *pp, struct of_geom *ptrgeom, FTYPE *Trad, FTYPE *nrad, FTYPE *expfactorrad);
759 static void calc_Trad(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q , FTYPE *Trad, FTYPE *nrad, FTYPE *expfactorrad);
760 static void calc_Trad_fromRuuandgamma(FTYPE *pp, struct of_geom *ptrgeom, FTYPE Ruu, FTYPE gammaradgas, FTYPE *Trad, FTYPE *nrad, FTYPE *expfactorrad);
761 
762 
763 
764 
766 #define FIMPLICITCALLTYPEF1 1
767 #define FIMPLICITCALLTYPEFINALCHECK 2
768 #define FIMPLICITCALLTYPEJAC 3
769 #define FIMPLICITCALLTYPEFINALCHECK2 4
770 
771 
772 
773 
774 
775 // KORALTODO: If solve for full RHO+MHD+RAD solution and iterate primitives instead, then can nominally better avoid out of bounds p(U) inversion. While involves 1+4+4=9 dimensional Newton's method, use of p(U) is avoided completely so saves lots of time. Only ever need to call U(p). But then doesn't take advantage of accurate(and reductions) for p(U).
776 
777 #define DIMTYPEFCONS 0
778 #define DIMTYPEFPRIM 1
779 
782 #define UTOPRIMGENWRAPPERRETURNNOFAIL (UTOPRIMNOFAIL)
783 #define UTOPRIMGENWRAPPERRETURNFAILRAD (1)
784 #define UTOPRIMGENWRAPPERRETURNFAILMHD (2)
785 
797 static int Utoprimgen_failwrapper(int doradonly, int *radinvmod, int showmessages, int checkoninversiongas, int checkoninversionrad, int allowlocalfailurefixandnoreport, int finalstep, int *eomtype, int whichcap, int evolvetype, int inputtype,FTYPE *U, struct of_state *qptr, struct of_geom *ptrgeom, FTYPE dissmeasure, FTYPE *pr, struct of_newtonstats *newtonstats)
798 {
799  int failreturn;
800  // defaults
801  failreturn=0;
802 
803 
804  int eomtypelocal=*eomtype;
805 
806 
807  // KORALTODO:
808  // flag needs to be reset to preexistingfail(gas/rad) is not a failure. Only use preexisting catches in utoprimgen.c if done with 4-force and report error in pflag and eventually go to the final advance.c inversion.
809  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMNOFAIL;
810  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADNOFAIL;
811 
812 
813  PFTYPE *lpflag,*lpflagrad;
814  lpflag=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
815  lpflagrad=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
816 
817 
818  if(doradonly==1){ // if doradonly==1, no need to call Utoprimgen() and no use for checkoninversiongas or checkoninversionrad
819  u2p_rad(showmessages, allowlocalfailurefixandnoreport,GAMMAMAXRADIMPLICITSOLVER,whichcap,U,pr,ptrgeom,lpflag,lpflagrad);
820  *radinvmod=(int)(*lpflagrad);
821  }
822  else{
823  //calculating primitives
824  // OPTMARK: Should optimize this to not try to get down to machine precision
825  int whichmethod=MODEDEFAULT; // means don't change method from eomtype.
826  int modprim=0;
827  // int checkoninversiongas=CHECKONINVERSION;
828  // int checkoninversionrad=CHECKONINVERSIONRAD;
829  MYFUN(Utoprimgen(showmessages,checkoninversiongas,checkoninversionrad, allowlocalfailurefixandnoreport, finalstep, &eomtypelocal, whichcap, whichmethod, modprim, evolvetype, inputtype, U, qptr, ptrgeom, dissmeasure, pr, pr, newtonstats),"phys.tools.rad.c:Utoprimgen_failwrapper()", "Utoprimgen", 1);
830  if(SWITCHTOENTROPYIFCHANGESTOENTROPY==1) *eomtype=eomtypelocal;
831  // else don't change
832  *radinvmod=(int)(*lpflagrad);
833  // *radinvmod=0; //KORALTODO: Not using method that needs this call, so for now don't pass radinvmod through to Utoprimgen().
834  nstroke+=(newtonstats->nstroke);
835  // this can change eomtype
836  }
837 
838  // check how inversion did. If didn't succeed, then check if soft failure and pass. Else if hard failure have to return didn't work.
839  if(IFUTOPRIMFAILSOFT(*lpflag)){
840  // assume soft failure ok, but reset
841  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL)=UTOPRIMNOFAIL;
842  prod0dualfprintf(showmessages && debugfail>=2,fail_file,"Got soft MHD failure inversion failure during Utoprimgen_failwrapper: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
843  }
844  else if(IFUTOPRIMRADHARDFAIL(*lpflagrad)){
845  // can reduce Newton step if getting failure.
846  // reset pflag for radiation to no failure, but treat here locally
847  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADNOFAIL;
848  prod0dualfprintf(showmessages && debugfail>=2,fail_file,"Got some radiation inversion failure during Utoprimgen_failwrapper: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
850  }
851  else if( IFUTOPRIMFAIL(*lpflag) || IFUTOPRIMRADHARDFAIL(*lpflagrad) ){
852  // these need to get fixed-up, but can't, so return failure
853  prod0dualfprintf(showmessages && debugfail>=2,fail_file,"Got hard failure of inversion (MHD part only considered as hard) in f_implicit(): ijk=%d %d %d : %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,*lpflag,*lpflagrad);
855  }
856  else if(PRODUCTION==0){
857  // no failure
858  // prod0dualfprintf(1,fail_file,"No failure in Utoprimgen_failwrapper: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
859  }
860 
861 
862  //DEBUG:
863 #if(PRODUCTION==0)
864  if(debugfail>=2 && showmessages){
865  struct of_state q;
866  MYFUN(get_stateforcheckinversion(pr, ptrgeom, &q),"flux.c:fluxcalc()", "get_state()", 1);
867  int outputtype=inputtype;
868  FTYPE Unew[NPR];
869  MYFUN(primtoU(outputtype,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
870  int pliter,pl;
871  PLOOP(pliter,pl) dualfprintf(fail_file,"COMPARE: pl=%d pr=%g U=%g Unew=%g\n",pl,pr[pl],U[pl],Unew[pl]);
872  int jj;
873  DLOOPA(jj) dualfprintf(fail_file,"COMPARE: jj=%d uradcon=%g uradcov=%g\n",jj,q.uradcon[jj],q.uradcov[jj]);
874  DLOOPA(jj) dualfprintf(fail_file,"COMPARE: jj=%d ucon=%g ucov=%g\n",jj,q.ucon[jj],q.ucov[jj]);
875  }
876  //DEBUG:
877  if((showmessages || debugfail>=2)){
878  static int maxlntries=0,maxnstroke=0;
879  int diff;
880  diff=0;
881  // For RADSHADOW, gets up to 5
882  if(newtonstats->lntries>maxlntries){ maxlntries=newtonstats->lntries; diff=1;}
883  if(newtonstats->nstroke>maxnstroke){ maxnstroke=newtonstats->nstroke; diff=1;}
884  // only report if grew beyond prior maximum
885  if(diff) dualfprintf(fail_file,"newtonsteps: lntries=%d (max=%d) nstroke=%d (max=%d) logerror=%g\n",newtonstats->lntries,maxlntries,newtonstats->nstroke,maxnstroke,newtonstats->lerrx);
886  }
887 #endif
888 
889  // return failure mode of inversion U->P
890  return(failreturn);
891 }
892 
893 
894 
895 
896 
897 
898 
899 
900 
901 
902 
903 
904 
905 
906 
907 
908 
909 
910 
911 
917 #define QTYUMHD 0 // iter or ferr
918 #define QTYUMHDENERGYONLY 1 // ferr only for now
919 #define QTYUMHDMOMONLY 2 // ferr only for now
920 #define QTYURAD 3 // iter or ferr
921 #define QTYURADENERGYONLY 4 // ferr only for now
922 #define QTYURADMOMONLY 5 // ferr only for now
923 #define QTYPMHD 6 // only iter
924 #define QTYPMHDENERGYONLY 7 // iter
925 #define QTYPMHDMOMONLY 8 // iter
926 #define QTYPRAD 9 // only iter
927 #define QTYPRADENERGYONLY 10 // only iter
928 #define QTYPRADMOMONLY 11 // only iter
929 #define QTYENTROPYUMHD 12 // iter or ferr
930 #define QTYENTROPYUMHDENERGYONLY 13 // ferr only for now
931 #define QTYENTROPYUMHDMOMONLY 14 // ferr only for now
932 #define QTYENTROPYPMHD 15 // iter (not used)
933 #define QTYENTROPYPMHDENERGYONLY 16 // iter (not used)
934 #define QTYENTROPYPMHDMOMONLY 17 // iter (not used)
935 
936 
938 #define IMPPTYPE(implicititer) (implicititer==QTYPMHD ||implicititer==QTYPMHDENERGYONLY ||implicititer==QTYPMHDMOMONLY || implicititer==QTYPRAD ||implicititer==QTYPRADENERGYONLY ||implicititer==QTYPRADMOMONLY || implicititer==QTYENTROPYPMHD ||implicititer==QTYENTROPYPMHDENERGYONLY ||implicititer==QTYENTROPYPMHDMOMONLY)
939 
940 #define IMPUTYPE(implicititer) (implicititer==QTYUMHD ||implicititer==QTYUMHDENERGYONLY ||implicititer==QTYUMHDMOMONLY || implicititer==QTYURAD ||implicititer==QTYURADENERGYONLY ||implicititer==QTYURADMOMONLY || implicititer==QTYENTROPYUMHD ||implicititer==QTYENTROPYUMHDENERGYONLY ||implicititer==QTYENTROPYUMHDMOMONLY)
941 
943 #define IMPMHDTYPE(implicititer) (implicititer==QTYPMHD ||implicititer==QTYPMHDENERGYONLY ||implicititer==QTYPMHDMOMONLY || implicititer==QTYUMHD ||implicititer==QTYUMHDENERGYONLY ||implicititer==QTYUMHDMOMONLY || implicititer==QTYENTROPYUMHD ||implicititer==QTYENTROPYUMHDENERGYONLY ||implicititer==QTYENTROPYUMHDMOMONLY)
944 
945 #define IMPRADTYPE(implicititer) (implicititer==QTYPRAD ||implicititer==QTYPRADENERGYONLY ||implicititer==QTYPRADMOMONLY || implicititer==QTYURAD ||implicititer==QTYURADENERGYONLY ||implicititer==QTYURADMOMONLY)
946 
948 #define IMPMHDTYPEBASE(baseitermethod) (baseitermethod==QTYPMHD || baseitermethod==QTYUMHD || baseitermethod==QTYENTROPYUMHD)
949 
950 #define IMPRADTYPEBASE(baseitermethod) (baseitermethod==QTYPRAD || baseitermethod==QTYURAD)
951 
953 #define IMPPMHDTYPE(implicititer) (implicititer==QTYPMHD ||implicititer==QTYPMHDENERGYONLY ||implicititer==QTYPMHDMOMONLY)
954 
955 
956 
959 static void define_method(int iter, int *eomtype, int itermode, int baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, struct of_method *mtd)
960 {
961  int eomtypelocal=*eomtype; // default, but not changing it so far.
962 
963 
964  if(eomtypelocal==EOMDEFAULT){
965  eomtypelocal=EOMTYPE; // override
966  }
967 
968 
969 #if(PRODUCTION==0)
970  if(EOMDONOTHING(eomtypelocal)){
971  dualfprintf(fail_file,"Can't have EOMDONOTHING in radiation code.\n");
972  myexit(938463651);
973  }
974 #endif
975 
976 
977  if(itermode==ITERMODESTAGES){
980 
983 
986 
988  }
989  else if(itermode==ITERMODENORMAL){
990  mtd->BEGINMOMSTEPS=-1;
991  mtd->ENDMOMSTEPS=-1;
992 
993  mtd->BEGINENERGYSTEPS=-1;
994  mtd->ENDENERGYSTEPS=-1;
995 
996  mtd->BEGINFULLSTEPS=1;
997  mtd->ENDFULLSTEPS=(IMPMAXITERLONG*2);
998 
999  mtd->BEGINNORMALSTEPS=1; // has to be consistent with actual first iteration, which is currently 1.
1000  }
1001  else if(itermode==ITERMODECOLD){
1002  mtd->BEGINMOMSTEPS=1;
1003  mtd->ENDMOMSTEPS=IMPMAXITERLONG*2;
1004 
1005  mtd->BEGINENERGYSTEPS=-1;
1006  mtd->ENDENERGYSTEPS=-1;
1007 
1008  mtd->BEGINFULLSTEPS=-1;
1009  mtd->ENDFULLSTEPS=-1;
1010 
1011  mtd->BEGINNORMALSTEPS=1;
1012  }
1013  else{
1014 #if(PRODUCTION==0)
1015  dualfprintf(fail_file,"No such itermode=%d\n",itermode);
1016  myexit(30486346);
1017 #endif
1018  }
1019 
1020 
1021 
1022 
1024  if(eomtypelocal==EOMGRMHD||eomtypelocal==EOMCOLDGRMHD){
1025 
1027  // V1: Works fine, but slow. Gives hot fluid near jumps like torus edge. Computing UU[ENTROPY] with or without source doesn't change much.
1028  //mtd->implicititer=(QTYURAD); // choice
1029  //mtd->implicitferr=(QTYURAD); // choice
1030 
1032  // V1: Ok unless entropy source added.
1033  //mtd->implicititer=(QTYUMHD); // choice
1034  //mtd->implicitferr=(QTYUMHD); // choice
1035 
1037  // V1: unstable with entropy source
1038  //mtd->implicititer=(QTYPRAD);
1039  //mtd->implicitferr=(QTYURAD);
1040 
1041 
1042  if(DOSUBJAC==1){
1043  // assume iter=1 is first iteration
1044  if(iter>=mtd->BEGINMOMSTEPS && iter<=mtd->ENDMOMSTEPS){
1045  if(baseitermethod==QTYPMHD){
1046  mtd->implicititer=(QTYPMHDMOMONLY); // choice
1048  }
1049  else if(baseitermethod==QTYURAD){
1050  mtd->implicititer=(QTYURADMOMONLY); // choice
1051  mtd->implicitferr=(QTYURADMOMONLY); // choice
1052  }
1053  else if(baseitermethod==QTYPRAD){
1054  mtd->implicititer=(QTYPRADMOMONLY); // choice
1055  mtd->implicitferr=(QTYURADMOMONLY); // choice
1056  }
1057  }
1058  else if(iter>=mtd->BEGINENERGYSTEPS && iter<=mtd->ENDENERGYSTEPS){
1059  if(baseitermethod==QTYPMHD){
1060  mtd->implicititer=(QTYPMHDENERGYONLY); // choice
1062  }
1063  else if(baseitermethod==QTYURAD){
1064  mtd->implicititer=(QTYURADENERGYONLY); // choice
1066  }
1067  else if(baseitermethod==QTYPRAD){
1068  mtd->implicititer=(QTYPRADENERGYONLY); // choice
1070  }
1071  }
1072  else if(iter>=mtd->BEGINFULLSTEPS && iter<=mtd->ENDFULLSTEPS){
1073  if(baseitermethod==QTYPMHD){
1074  // V1: noisy in atmosphere and torus edge, but otherwise ok.
1075  mtd->implicititer=(QTYPMHD); // choice
1076  mtd->implicitferr=(QTYUMHD);
1077  }
1078  else if(baseitermethod==QTYURAD){
1079  mtd->implicititer=(QTYURAD); // choice
1080  mtd->implicitferr=(QTYURAD); // choice
1081  }
1082  else if(baseitermethod==QTYPRAD){
1083  mtd->implicititer=(QTYPRAD); // choice
1084  mtd->implicitferr=(QTYURAD); // choice
1085  }
1086  }
1087  else{
1088 #if(PRODUCTION==0)
1089  dualfprintf(fail_file,"A Not setup for iter=%d %d %d %g : %d %d : %d %d : %d %d : %d : %d\n",iter, *eomtype, itermode, fracenergy, mtd->BEGINMOMSTEPS, mtd->ENDMOMSTEPS, mtd->BEGINENERGYSTEPS, mtd->ENDENERGYSTEPS, mtd->BEGINFULLSTEPS, mtd->ENDFULLSTEPS, mtd->BEGINNORMALSTEPS,baseitermethod);
1090  myexit(3498346457);
1091 #endif
1092  }
1093  }
1094  else{
1095  if(baseitermethod==QTYPMHD){
1096  mtd->implicititer=(QTYPMHD); // choice
1097  mtd->implicitferr=(QTYUMHD);
1098  }
1099  else if(baseitermethod==QTYURAD){
1100  mtd->implicititer=(QTYURAD); // choice
1101  mtd->implicitferr=(QTYURAD); // choice
1102  }
1103  else if(baseitermethod==QTYPRAD){
1104  mtd->implicititer=(QTYPRAD); // choice
1105  mtd->implicitferr=(QTYURAD); // choice
1106  }
1107  }
1108  }
1109  else if(eomtypelocal==EOMENTROPYGRMHD){
1110 
1112  // V2: Like V1 but goes unstable.
1113  //mtd->implicititer=(QTYUMHD); // choice
1114  //mtd->implicitferr=(QTYENTROPYUMHD); // choice
1115 
1116 
1117  if(DOSUBJAC==1){
1118  // assume iter=1 is first iteration
1119  if(iter>=mtd->BEGINMOMSTEPS && iter<=mtd->ENDMOMSTEPS){
1120  if(baseitermethod==QTYPMHD){
1121  mtd->implicititer=(QTYPMHDMOMONLY); // choice
1123  }
1124  else if(baseitermethod==QTYENTROPYUMHD){
1127  }
1128  else if(baseitermethod==QTYURAD){
1129  mtd->implicititer=(QTYURADMOMONLY); // choice
1130  mtd->implicitferr=(QTYURADMOMONLY); // choice
1131  }
1132  else if(baseitermethod==QTYPRAD){
1133  mtd->implicititer=(QTYPRADMOMONLY); // choice
1134  mtd->implicitferr=(QTYURADMOMONLY); // choice
1135  }
1136  }
1137  else if(iter>=mtd->BEGINENERGYSTEPS && iter<=mtd->ENDENERGYSTEPS){
1138  if(baseitermethod==QTYPMHD){
1139  mtd->implicititer=(QTYPMHDENERGYONLY); // choice
1141  }
1142  else if(baseitermethod==QTYENTROPYUMHD){
1145  }
1146  else if(baseitermethod==QTYURAD){
1147  mtd->implicititer=(QTYURADENERGYONLY); // choice
1148  mtd->implicitferr=(QTYURADENERGYONLY); // choice
1149  }
1150  else if(baseitermethod==QTYPRAD){
1151  mtd->implicititer=(QTYPRADENERGYONLY); // choice
1153  }
1154  }
1155  else if(iter>=mtd->BEGINFULLSTEPS && iter<=mtd->ENDFULLSTEPS){
1156  if(baseitermethod==QTYPMHD){
1157  // V2: perfectly fine as entropy method
1158  mtd->implicititer=(QTYPMHD); // choice
1159  mtd->implicitferr=(QTYENTROPYUMHD); // choice
1160  }
1161  else if(baseitermethod==QTYENTROPYUMHD){
1162  // V1: works perfectly fine and acts like PMHD,ENTROPYUMHD method just slower:
1165  }
1166  else if(baseitermethod==QTYURAD){
1167  mtd->implicititer=(QTYURAD); // choice
1168  mtd->implicitferr=(QTYURAD); // choice
1169  }
1170  else if(baseitermethod==QTYPRAD){
1171  mtd->implicititer=(QTYPRAD); // choice
1172  mtd->implicitferr=(QTYURAD);
1173  }
1174  }
1175  else{
1176 #if(PRODUCTION==0)
1177  dualfprintf(fail_file,"B Not setup for iter=%d %d %d %g : %d %d : %d %d : %d %d : %d : %d\n",iter, *eomtype, itermode, fracenergy, mtd->BEGINMOMSTEPS, mtd->ENDMOMSTEPS, mtd->BEGINENERGYSTEPS, mtd->ENDENERGYSTEPS, mtd->BEGINFULLSTEPS, mtd->ENDFULLSTEPS, mtd->BEGINNORMALSTEPS,baseitermethod);
1178  myexit(3498346458);
1179 #endif
1180  }
1181  }
1182  else{
1183  if(baseitermethod==QTYPMHD){
1184  mtd->implicititer=(QTYPMHD); // choice
1185  mtd->implicitferr=(QTYENTROPYUMHD); // choice
1186  }
1187  else if(baseitermethod==QTYENTROPYUMHD){
1190  }
1191  else if(baseitermethod==QTYURAD){
1192  mtd->implicititer=(QTYURAD); // choice
1193  mtd->implicitferr=(QTYURAD); // choice
1194  }
1195  else if(baseitermethod==QTYPRAD){
1196  mtd->implicititer=(QTYPRAD); // choice
1197  mtd->implicitferr=(QTYURAD);
1198  }
1199  }
1200  }
1201  else{
1202 #if(PRODUCTION==0)
1203  dualfprintf(fail_file,"No such eomtypelocal=%d in define_method\n",eomtypelocal);
1204  myexit(938463653);
1205 #endif
1206  }
1207 
1208  // TESTING:
1209  //mtd->implicititer=(QTYURAD); // choice
1210  //mtd->implicitferr=(QTYURAD); // choice
1211 
1212 
1213 }
1214 
1215 
1216 
1217 #if(0)
1218 #define JACNPR (NDIM+1) // maximum number of terms in Jacobian
1219 #define JACNUMTYPES 5
1220 #define JNORMALTYPE 0
1221 #define JALTTYPE 1
1222 #define JSUPERFULLTYPE 2
1223 #define JFULLERRORTYPE 3
1224 #define JSUBERRORTYPE 4
1225 int jacstart[JACNUMTYPES],jaclist[JACNUMTYPES][JACNPR],jacend[JACNUMTYPES];
1226 #define JACTYPELOOP(type) for(type=0;type<JACNUMTYPES;type++)
1227 #define JACALLLOOP(pl) for(pl=0;pl<JACNPR;pl++)
1228 #define JACLOOP(type,pliter,pl) for(pliter=jacstart[type],pl=jaclist[type][pliter];pliter<=jacend[type];pliter++,pl=jaclist[type][pliter])
1229 #endif
1230 
1231 
1232 #define JACNPR (NDIM)
1233 #define JACLOOP(jj,startjj,endjj) for(jj=startjj;jj<=endjj;jj++)
1234 #define JACLOOPALT(jj,startjj,endjj) DLOOPA(jj) //for(jj=startjj;jj<=endjj;jj++) // for those things might or might not want to do all terms
1235 
1236 // over f's, not primitives, to determine error
1237 #define JACLOOPSUPERFULL(pliter,pl,eomtype,baseitermethod,radinvmod) PLOOPDYNAMICAL(pliter,pl) if(\
1238 pl!=ENTROPY && pl!=UU && pl!=URAD0 \
1239 || (eomtype==EOMDEFAULT && EOMTYPE==EOMENTROPYGRMHD || eomtype==EOMENTROPYGRMHD || eomtype==EOMDIDENTROPYGRMHD) \
1240  && (pl==ENTROPY || pl==URAD0 && IMPMHDTYPEBASE(baseitermethod)==0 || IMPMHDTYPEBASE(baseitermethod)==1 && (pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==0 || pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==1 && radinvmod==0)) \
1241 || (eomtype==EOMDEFAULT && EOMTYPE==EOMGRMHD || eomtype==EOMGRMHD || eomtype==EOMDIDGRMHD) \
1242  && (pl==UU || pl==URAD0 && IMPMHDTYPEBASE(baseitermethod)==0 || IMPMHDTYPEBASE(baseitermethod)==1 && (pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==0 || pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==1 && radinvmod==0) ) \
1243 )
1244 
1245 //#define JACLOOPSUPERFULL(pliter,pl,eomtype,baseitermethod,radinvmod) PLOOP(pliter,pl) if(pl!=ENTROPY && pl!=UU && pl!=URAD0 && !SCALARPL(pl) || (eomtype==EOMDEFAULT && EOMTYPE==EOMENTROPYGRMHD || eomtype==EOMENTROPYGRMHD || eomtype==EOMDIDENTROPYGRMHD) && (pl==ENTROPY || pl==URAD0 && IMPMHDTYPEBASE(baseitermethod)==0 || IMPMHDTYPEBASE(baseitermethod)==1 && (pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==0 || pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==1 && radinvmod==0)) || (eomtype==EOMDEFAULT && EOMTYPE==EOMGRMHD || eomtype==EOMGRMHD || eomtype==EOMDIDGRMHD) && (pl==UU || pl==URAD0 && IMPMHDTYPEBASE(baseitermethod)==0 || IMPMHDTYPEBASE(baseitermethod)==1 && (pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==0 || pl==URAD0 && AVOIDURAD0IFRADINVMODANDPMHDMETHOD==1 && radinvmod==0) )) // over f's, not primitives.
1246 #define JACLOOPFULLERROR(itermode,jj,startjj,endjj) for(jj=(itermode==ITERMODECOLD ? startjj : 0);jj<=(itermode==ITERMODECOLD ? endjj : NDIM-1);jj++)
1247 #define JACLOOPSUBERROR(jj,startjj,endjj) JACLOOP(jj,startjj,endjj)
1248 #define JACLOOP2D(ii,jj,startjj,endjj) JACLOOP(ii,startjj,endjj) JACLOOP(jj,startjj,endjj)
1249 
1250 #if(0)
1251 static void get_refUs(int *numdims, int *startjac, int *endjac, int *implicititer, int *implicitferr, int *irefU, int *iotherU, int *erefU, int *eotherU, int *signgd2, int *signgd4, int *signgd6, int *signgd7)
1252 {
1253  int jj;
1254  int type;
1255 
1256 
1257  // default
1258 
1259  // default
1260  *numdims=jacend[JNORMALTYPE];
1261  *signgd7= (+1.0); // not used for PMHD
1262  DLOOPA(jj) irefU[jj]=UU+jj;
1263  DLOOPA(jj) iotherU[jj]=URAD0+jj;
1264  // *startjac=0; *endjac=NDIM-1;
1265 
1266  // same list and numbers in array for both primitives and conserved
1267  if(*implicititer==QTYUMHD || *implicititer==QTYPMHD){
1268  JACTYPELOOP(type){ jacstart[type]=0; jacend[type]=NDIM-1; DLOOPA(jj) jaclist[type][jj]=UU+jj; }
1269  }
1270  else if(*implicititer==QTYUMHDENERGYONLY || *implicititer==QTYPMHDENERGYONLY){
1271  // *startjac=0; *endjac=0;
1272  JACTYPELOOP(type){ jacstart[type]=0; jacend[type]=0; jaclist[type][0]=UU; }
1273  }
1274  else if(*implicititer==QTYUMHDMOMONLY || *implicititer==QTYPMHDMOMONLY){
1275  // *startjac=1; *endjac=3;
1276  JACTYPELOOP(type){ jacstart[type]=0; jacend[type]=2; SLOOPA(jj) jaclist[type][jj]=U1+jj-1; }
1277  }
1278  else if(*implicititer==QTYENTROPYUMHD || *implicititer==QTYENTROPYPMHD){
1279  irefU[TT]=ENTROPY;
1280  }
1281  else if(*implicititer==QTYENTROPYUMHDENERGYONLY){
1282  irefU[TT]=ENTROPY;
1283  *startjac=0; *endjac=0;
1284  }
1285  else if(*implicititer==QTYENTROPYUMHDMOMONLY){
1286  irefU[TT]=ENTROPY;
1287  *startjac=1; *endjac=3;
1288  }
1289  else if(*implicititer==QTYURAD || *implicititer==QTYPRAD){
1290  *numdims=NDIM;
1291  *signgd7= (+1.0); // required to make URAD method work for (e.g.) RADSHADOW if using Gddt-based GS
1292  DLOOPA(jj) irefU[jj]=URAD0+jj;
1293  DLOOPA(jj) iotherU[jj]=UU+jj;
1294  *startjac=0; *endjac=NDIM-1;
1295  }
1296  else if(*implicititer==QTYURADENERGYONLY || *implicititer==QTYPRADENERGYONLY){
1297  *numdims=NDIM;
1298  *signgd7= (+1.0);
1299  DLOOPA(jj) irefU[jj]=URAD0+jj;
1300  DLOOPA(jj) iotherU[jj]=UU+jj;
1301  *startjac=0; *endjac=0;
1302  }
1303  else if(*implicititer==QTYURADMOMONLY || *implicititer==QTYPRADMOMONLY){
1304  *numdims=NDIM;
1305  *signgd7= (+1.0);
1306  DLOOPA(jj) irefU[jj]=URAD0+jj;
1307  DLOOPA(jj) iotherU[jj]=UU+jj;
1308  *startjac=1; *endjac=3;
1309  }
1310  else if(PRODUCTION==0){
1311  dualfprintf(fail_file,"No such implicititer=%d\n",*implicititer);
1312  myexit(468346321);
1313  }
1314 
1315  // same list and numbers in array for both primitives and conserved
1316 
1317  //default
1318  *numdims=NDIM;
1319  DLOOPA(jj) erefU[jj]=UU+jj;
1320  DLOOPA(jj) eotherU[jj]=URAD0+jj;
1321 
1322  if(*implicitferr==QTYUMHD){
1323  }
1324  else if(*implicitferr==QTYUMHDENERGYONLY){
1325  }
1326  else if(*implicitferr==QTYUMHDMOMONLY){
1327  }
1328  else if(*implicitferr==QTYENTROPYUMHD){
1329  erefU[TT]=ENTROPY;
1330  }
1331  else if(*implicitferr==QTYENTROPYUMHDENERGYONLY){
1332  erefU[TT]=ENTROPY;
1333  }
1334  else if(*implicitferr==QTYENTROPYUMHDMOMONLY){
1335  erefU[TT]=ENTROPY;
1336  }
1337  else if(*implicitferr==QTYURAD){
1338  *numdims=NDIM;
1339  DLOOPA(jj) erefU[jj]=URAD0+jj;
1340  DLOOPA(jj) eotherU[jj]=UU+jj;
1341  }
1342  else if(*implicitferr==QTYURADENERGYONLY){
1343  *numdims=NDIM;
1344  DLOOPA(jj) erefU[jj]=URAD0+jj;
1345  DLOOPA(jj) eotherU[jj]=UU+jj;
1346  }
1347  else if(*implicitferr==QTYURADMOMONLY){
1348  *numdims=NDIM;
1349  DLOOPA(jj) erefU[jj]=URAD0+jj;
1350  DLOOPA(jj) eotherU[jj]=UU+jj;
1351  }
1352  else if(PRODUCTION==0){
1353  dualfprintf(fail_file,"No such implicitferr=%d\n",*implicitferr);
1354  myexit(468346322);
1355  }
1356 
1357  // sign that goes into implicit differencer that's consistent with sign for *signgd of -1 when using the radiative uu to measure f.
1358  *signgd2=(+1.0);
1359  *signgd4=(+1.0); // for entropy alone for Gdpl in error function // Appears for QTYUMHD,QTYENTROPYUMHD this sign is the right one. But both cases have lots of cold MHD inversions.
1360  *signgd6=(-1.0); // for entropy as goes into GS from dUrad or dUmhd // // KORALTODO SUPERGODMARK: -- unsure about sign!
1361 
1362 
1364  //
1365  // Fix jacobian lists for including NRAD, which must always be included when doing full steps.
1366  //
1368  if(NRAD>=0){
1369  JACTYPELOOP(type){
1370  jacend[type]++;
1371  jaclist[type][jacend[type]-1]=NRAD;
1372  }
1373  }
1374 
1375 
1376 }
1377 #endif
1378 
1379 
1380 
1381 static void get_refUs(struct of_method *mtd, struct of_refU *ru)
1382 {
1383  int jj;
1384 
1385  // default
1386  ru->numdims=NDIM;
1387  ru->signgd7= (+1.0); // not used for PMHD
1388  DLOOPA(jj) ru->irefU[jj]=UU+jj;
1389  DLOOPA(jj) ru->iotherU[jj]=URAD0+jj;
1390  ru->startjac=0; ru->endjac=NDIM-1;
1391 
1392  // same list and numbers in array for both primitives and conserved
1393  if(mtd->implicititer==QTYUMHD || mtd->implicititer==QTYPMHD){
1394  }
1396  ru->startjac=0; ru->endjac=0;
1397  }
1398  else if(mtd->implicititer==QTYUMHDMOMONLY || mtd->implicititer==QTYPMHDMOMONLY){
1399  ru->startjac=1; ru->endjac=3;
1400  }
1401  else if(mtd->implicititer==QTYENTROPYUMHD || mtd->implicititer==QTYENTROPYPMHD){
1402  ru->irefU[TT]=ENTROPY;
1403  }
1404  else if(mtd->implicititer==QTYENTROPYUMHDENERGYONLY){
1405  ru->irefU[TT]=ENTROPY;
1406  ru->startjac=0; ru->endjac=0;
1407  }
1408  else if(mtd->implicititer==QTYENTROPYUMHDMOMONLY){
1409  ru->irefU[TT]=ENTROPY;
1410  ru->startjac=1; ru->endjac=3;
1411  }
1412  else if(mtd->implicititer==QTYURAD || mtd->implicititer==QTYPRAD){
1413  ru->numdims=NDIM;
1414  ru->signgd7= (+1.0); // required to make URAD method work for (e.g.) RADSHADOW if using Gddt-based GS
1415  DLOOPA(jj) ru->irefU[jj]=URAD0+jj;
1416  DLOOPA(jj) ru->iotherU[jj]=UU+jj;
1417  ru->startjac=0; ru->endjac=NDIM-1;
1418  }
1419  else if(mtd->implicititer==QTYURADENERGYONLY || mtd->implicititer==QTYPRADENERGYONLY){
1420  ru->numdims=NDIM;
1421  ru->signgd7= (+1.0);
1422  DLOOPA(jj) ru->irefU[jj]=URAD0+jj;
1423  DLOOPA(jj) ru->iotherU[jj]=UU+jj;
1424  ru->startjac=0; ru->endjac=0;
1425  }
1426  else if(mtd->implicititer==QTYURADMOMONLY || mtd->implicititer==QTYPRADMOMONLY){
1427  ru->numdims=NDIM;
1428  ru->signgd7= (+1.0);
1429  DLOOPA(jj) ru->irefU[jj]=URAD0+jj;
1430  DLOOPA(jj) ru->iotherU[jj]=UU+jj;
1431  ru->startjac=1; ru->endjac=3;
1432  }
1433  else{
1434 #if(PRODUCTION==0)
1435  dualfprintf(fail_file,"No such implicititer=%d\n",mtd->implicititer);
1436  myexit(468346321);
1437 #endif
1438  }
1439 
1440  // same list and numbers in array for both primitives and conserved
1441 
1442  //default
1443  ru->numdims=NDIM;
1444  DLOOPA(jj) ru->erefU[jj]=UU+jj;
1445  DLOOPA(jj) ru->eotherU[jj]=URAD0+jj;
1446 
1447  if(mtd->implicitferr==QTYUMHD){
1448  }
1449  else if(mtd->implicitferr==QTYUMHDENERGYONLY){
1450  }
1451  else if(mtd->implicitferr==QTYUMHDMOMONLY){
1452  }
1453  else if(mtd->implicitferr==QTYENTROPYUMHD){
1454  ru->erefU[TT]=ENTROPY;
1455  }
1456  else if(mtd->implicitferr==QTYENTROPYUMHDENERGYONLY){
1457  ru->erefU[TT]=ENTROPY;
1458  }
1459  else if(mtd->implicitferr==QTYENTROPYUMHDMOMONLY){
1460  ru->erefU[TT]=ENTROPY;
1461  }
1462  else if(mtd->implicitferr==QTYURAD){
1463  ru->numdims=NDIM;
1464  DLOOPA(jj) ru->erefU[jj]=URAD0+jj;
1465  DLOOPA(jj) ru->eotherU[jj]=UU+jj;
1466  }
1467  else if(mtd->implicitferr==QTYURADENERGYONLY){
1468  ru->numdims=NDIM;
1469  DLOOPA(jj) ru->erefU[jj]=URAD0+jj;
1470  DLOOPA(jj) ru->eotherU[jj]=UU+jj;
1471  }
1472  else if(mtd->implicitferr==QTYURADMOMONLY){
1473  ru->numdims=NDIM;
1474  DLOOPA(jj) ru->erefU[jj]=URAD0+jj;
1475  DLOOPA(jj) ru->eotherU[jj]=UU+jj;
1476  }
1477  else{
1478 #if(PRODUCTION==0)
1479  dualfprintf(fail_file,"No such implicitferr=%d\n",mtd->implicitferr);
1480  myexit(468346322);
1481 #endif
1482  }
1483 
1484  // sign that goes into implicit differencer that's consistent with sign for signgd of -1 when using the radiative uu to measure f.
1485  ru->signgd2=(+1.0);
1486  ru->signgd4=(+1.0); // for entropy alone for Gdpl in error function // Appears for QTYUMHD,QTYENTROPYUMHD this sign is the right one. But both cases have lots of cold MHD inversions.
1487  ru->signgd6=(-1.0); // for entropy as goes into GS from dUrad or dUmhd // // KORALTODO SUPERGODMARK: -- unsure about sign!
1488 
1489 }
1490 
1491 
1492 
1493 static void setgasinversionstuff(int iter, int whichcall, FTYPE impeps, FTYPE errorabs, FTYPE convabs, int maxiter, struct of_newtonstats *newtonstats, int *checkoninversiongas, int *checkoninversionrad)
1494 {
1495  setnewtonstatsdefault(newtonstats);
1496  // initialize counters
1497  newtonstats->nstroke=newtonstats->lntries=0;
1498  // set inputs for errors, maxiters, etc.
1500  // try lowest error allowed, may be raised a bit in MHD inversion code.
1501  // min between normal desired error and iterated-quantity error. This seeks low error if iterated got low error, while avoids excessive attempt if not.
1502  newtonstats->tryconv=1E-2*MIN(convabs,errorabs); // NUMEPSILON
1503  newtonstats->tryconvultrarel=1E-2*MIN(convabs,errorabs); // NUMEPSILON
1504  newtonstats->extra_newt_iter=1; // KORALNOTE: apparently should keep this as >=1 to ensure error really drops
1505  newtonstats->extra_newt_iter_ultrarel=2; // KORALNOTE: apparently should keep this as >=1 to ensure error really drops
1506  }
1507  else{
1508  // KORALNOTE: If make newtonstats->tryconv~convabs, then if convabs~1E-12, then MHD inversion may return error~1E-10 in terms of how measured with f_error_check(), so must try harder than expected.
1509  newtonstats->tryconv=convabs*1E-2;
1510  newtonstats->tryconvultrarel=convabs*1E-2; // just bit smaller, not as extreme as default
1511  newtonstats->extra_newt_iter=1; // KORALNOTE: apparently should keep this as >=1 to ensure error really drops
1512  newtonstats->extra_newt_iter_ultrarel=1; // KORALNOTE: apparently should keep this as >=1 to ensure error really drops
1513  }
1514  // newtonstats->mintryconv=allowconvabs;
1516  newtonstats->maxiter=maxiter;
1517  // override with less strict error for Jacobian calculation
1518  if(whichcall==FIMPLICITCALLTYPEJAC){
1519  newtonstats->tryconv=MAX(impeps*1E-2,newtonstats->tryconv);
1520  newtonstats->tryconvultrarel=MAX(impeps*1E-3,newtonstats->tryconvultrarel);
1521  }
1522 
1523 
1524  // set whether should check inversion result inside Utoprimgen()
1525  if(whichcall==FIMPLICITCALLTYPEFINALCHECK || whichcall==FIMPLICITCALLTYPEFINALCHECK2){
1526  *checkoninversiongas=*checkoninversionrad=1;
1527  }
1528  else{
1529  // don't check since slows down code and could be good enough solution if original error says ok.
1530  *checkoninversiongas=*checkoninversionrad=0;
1531  }
1532 
1533 }
1534 
1535 
1536 
1554 static int f_implicit(int allowbaseitermethodswitch, int iter, int f1iter, int failreturnallowable, int whichcall, FTYPE impeps, int showmessages, int showmessagesheavy, int allowlocalfailurefixandnoreport, int *eomtype, int whichcap, int itermode, int *baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, int *radinvmod, FTYPE conv, FTYPE convabs, FTYPE allowconvabs, int maxiter, FTYPE realdt, int dimtypef, FTYPE *dimfactU, FTYPE *ppprev, FTYPE *pp, FTYPE *piin, FTYPE *uuprev, FTYPE *Uiin, FTYPE *uu0,FTYPE *uu,FTYPE localdt, struct of_geom *ptrgeom, struct of_state *q, FTYPE *f, FTYPE *fnorm, FTYPE *freport, int *goexplicit, FTYPE *errorabs, FTYPE *errorallabs, int whicherror, int *convreturn, int *nummhdinvsreturn, FTYPE *tautotmaxreturn, struct of_method *mtd, struct of_refU *ru)
1555 {
1556  int pliter, pl;
1557  int iv;
1558  struct of_newtonstats newtonstats;
1559  int checkoninversiongas=0;
1560  int checkoninversionrad=0;
1561  int finalstep = 0; //can choose either 1 or 0 depending on whether want floor-like fixups (1) or not (0). unclear which one would work best since for Newton method to converge might want to allow negative density on the way to the correct solution, on the other hand want to prevent runaway into rho < 0 region and so want floors.
1562  FTYPE Gdpl[NPR]={0.0},Gdplabs[NPR]={0.0}, Tgas={0.0},Trad={0.0};
1563  int failreturn;
1564  FTYPE uuabs[NPR]={0.0};
1565 
1566 
1567 
1568 
1569 
1570  // default is no failure
1571  failreturn=0;
1572 
1573 
1574 
1576  //
1577  // 0) backup pp and uu and prepare alternative versions
1578  //
1580  struct of_state qbackup;
1581  FTYPE ppbackup[NPR],uubackup[NPR]={0.0};
1582  FTYPE ppalt[NPR]={0.0},uualt[NPR]={0.0};
1583  int radinvmodbackup,radinvmodalt,failreturnalt;
1584  PLOOP(pliter,pl){
1585  ppalt[pl]=ppbackup[pl]=pp[pl];
1586  uualt[pl]=uubackup[pl]=uu[pl];
1587  }
1588  qbackup=*q;
1589  radinvmodbackup=*radinvmod;
1590 
1591 
1592 
1593 
1594 #if(MODEMETHOD==MODEENERGY ||MODEMETHOD==MODEENTROPY ||MODEMETHOD==MODESWITCH) // currently only ones that allow change
1595 
1596  //
1597  // setup method and signs (only needed per f_implicit if baseitermethod can change, because already do per iter in main implicit loop
1598  //
1600  define_method(iter, eomtype, itermode, *baseitermethod, fracenergy, dissmeasure, &mtd);
1601  get_refUs(&mtd, &ru);
1602 #endif
1603 
1604 
1605 
1606 
1607 
1608 
1609  // optimize whether need to really compute entropy with log/pow so slow
1610  int needentropy=1; // default get uu[entropy] and q->entropy
1611 #if(ENTROPYOPT)
1612  // whichcall==FIMPLICITCALLTYPEFINALCHECK means final check where if wasn't computing entropy during iterations, need at end so next RK substeps have it ready
1614  needentropy=1;
1615  }
1616  else needentropy=0;
1617 #else
1618  // then assume might need entropy generally
1619  needentropy=1;
1620 #endif
1621 
1622 
1623 
1624 
1625 
1626  //1) Reorder URAD method so:
1627  // a) URAD
1628  // b) URAD->PRAD
1629  // c) Re-get URAD(PRAD) in case floors/ceilings
1630  // d) Apply relative 4-force condition using this new URAD -> UGAS
1631  // e) UGAS->PGAS
1632  // f) Re-get UGAS(PGAS) in case floors/celings/failures/errors/etc.
1633  //
1634  // As long as MHD doesn't fail, then even if RAD hits ceilings, the solution will be in relative force balance. -- i.e. total energy-momentum conservation will hold despite change in URAD.
1635  //
1636  // Right now, I use pre-corrected URAD to get dUrad -> dUgas, so if rad hits ceilings while gas does not, then relative force balance is lost when could have been maintained.
1637  //
1638  // Need to have Utoprimgen() call without doing radiation inversion to save time .. doradonly=-1 ?
1639  //
1640  // BUT, if hit radinvmod with change in energy, then change in U would be dumped into GAS even if gas<<rad or tau\sim 0.
1641 
1642 
1643  // f_implicit_umhdurad(iter,uu,uu0,pp,q
1644 
1645 
1646 
1648  //
1649  // UMHD and URAD
1650  //
1652 
1653 
1654  if(
1656  || mtd->implicititer==QTYURAD || mtd->implicititer==QTYURADENERGYONLY || mtd->implicititer==QTYURADMOMONLY
1657  ){ // then don't yet have updated primitives, so invert to get them
1658  // 1) get change in conserved quantity between fluid and radiation (equal and opposite 4-force)
1659  // required for inversion to get P(U) for MHD and RAD variables
1660  // this preserves machine accurate conservation instead of applying 4-force on each fluid and radiation separately that can accumulate errors
1661  FTYPE Gddt[NDIM]; DLOOPA(iv) Gddt[iv]=(uu[ru->irefU[iv]]-uu0[ru->irefU[iv]]);
1662  DLOOPA(iv) uu[ru->iotherU[iv]] = uu0[ru->iotherU[iv]] - Gddt[iv];
1663  // reject what radiation says gas should be if forced into T^t_t<0 regime.
1664  int badchange=0;
1665  if(mtd->implicititer==QTYURAD || mtd->implicititer==QTYURADENERGYONLY || mtd->implicititer==QTYURADMOMONLY){
1666  if(
1667  REMOVERESTMASSFROMUU==2 && (uu[RHO]-uu[ru->iotherU[0]]<=0.0)
1668  ||REMOVERESTMASSFROMUU!=2 && (-uu[ru->iotherU[0]]<=0.0)
1669  ){
1670  badchange=1;
1671  }
1672  // can also go bad when momentum exceeds energy, but more complicated check for GRMHD -- so just do inversion
1673  }
1675  if(-uu[ru->iotherU[0]]<=0.0){
1676  badchange=1;
1677  }
1678  // inversion will catch when momentum exceeds energy.
1679  }
1680  // "revert" uu and ignore 4-force if badchange and just fail directly without expense of inversion.
1681  if(badchange && iter==1){
1682  // if first iteration, assume guess as (e.g.) Uiin, but can now change to uu0.
1683  PLOOP(pliter,pl) uu[pl] = uu0[pl];
1684  }
1685  else if(badchange){
1686  // only change other to uubackup (i.e. before 4-force applied)
1687  DLOOPA(iv) uu[ru->iotherU[iv]] = uubackup[ru->iotherU[iv]];
1688  }
1689  // 2) Get estimated U[entropy]
1690  // mathematica has Sc = Sc0 + dt *GS with GS = -u.G/T
1691  FTYPE GS=0.0;
1692  FTYPE Tgaslocal=0.0,Tradlocal=0.0;
1693  if(badchange==0){
1694  if(0){
1695  Tgaslocal=compute_temp_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pp[RHO],pp[UU]);
1696  get_state(pp, ptrgeom, q);
1697  DLOOPA(iv) GS += (-q->ucon[iv]*(ru->signgd2)*( (ru->signgd7)*Gddt[iv]))/(Tgaslocal+TEMPMIN); // maybe more accurate than just using entropy from pp and ucon[TT] from state from pp. __WORKINGONIT__: Can't be right that this is the same (signgd2=signgd7=1) for both URAD and UMHD methods.
1698  }
1699  else{
1700  // Get GS completely consisent with primitives, in case using entropy error function, because then shouldn't use Gddt[TT] related to energy equation.
1701  // Below rad inv may not be completely necessary, but not too expensive, so ok.
1702  int doradonly=1; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1703  int computestate=1;
1704  int computeentropy=1;
1705  koral_source_rad_calc(computestate,computeentropy,pp, ptrgeom, Gdpl, Gdplabs, NULL, &Tgaslocal, &Tradlocal, q);
1706  GS = - (ru->signgd4) * localdt * Gdpl[ENTROPY]/(ru->signgd6); // Consistent with uu = uu0 + signgd6*GS and how used when getting error function later
1707  }
1708  }
1709  uu[ENTROPY] = uu0[ENTROPY] + (ru->signgd6)*GS; // KORALTODO SUPERGODMARK: Problem with UMHD,UMHD no matter signgd7. Ok with URAD,URAD. Ok with UMHD,ENTROPYUMHD if signgd7 +1 and signgd4 +1.
1710  // 3) Do MHD+RAD Inversion
1711  // PLOOP(pliter,pl) dualfprintf(fail_file,"BEFORE: pl=%d pr=%g\n",pl,pp[pl]);
1712  setgasinversionstuff(iter,whichcall,impeps,*errorabs,convabs,maxiter,&newtonstats,&checkoninversiongas,&checkoninversionrad);
1713  int doradonly=0; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1714  *nummhdinvsreturn++;
1715 
1716  if(failreturn==UTOPRIMGENWRAPPERRETURNFAILRAD && whichcall==FIMPLICITCALLTYPEJAC){
1717  // then try other uu, even if total energy is not conserved, better than raditive failure leading to problems or innacuracy.
1718  PLOOP(pliter,pl) uu[pl] = uuprev[pl];
1719  doradonly=1; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1720  if(failreturn==UTOPRIMGENWRAPPERRETURNNOFAIL){
1721  int jjj;
1722  // DLOOPA(jjj) dualfprintf(fail_file,"DIDIT: jjj=%d uu=%21.15g\n",jjj,uu[URAD0+jjj]);
1723  }
1724  else{
1725  // dualfprintf(fail_file,"DIDITNOT\n");
1726  int jjj;
1727  SLOOPA(jjj){
1728  uu[URAD0+jjj]*=0.1;
1729  }
1730  // DLOOPA(jjj) dualfprintf(fail_file,"trying: jjj=%d uu=%21.15g\n",jjj,uu[URAD0+jjj]);
1731  doradonly=1; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1732  //doradonly=1; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu0, q, ptrgeom, dissmeasure, pp, &newtonstats);
1733  // if(failreturn==UTOPRIMGENWRAPPERRETURNNOFAIL) dualfprintf(fail_file,"DIDIT02\n");
1734  // else dualfprintf(fail_file,"DIDITNOT02\n");
1735  }
1736  }
1737 
1738 
1739 
1740  // When failreturn==UTOPRIMGENWRAPPERRETURNFAILMHD, Utoprimgen() passes back pp as initial guess, and when u(pp) is computed below, effectively didn't move uu[gas] away from uu0[gas]
1741  if(badchange) failreturn=UTOPRIMGENWRAPPERRETURNFAILMHD; // indicate that messed-up MHD inversion, without having to do the inversion.
1742  // PLOOP(pliter,pl) dualfprintf(fail_file,"AFTER: pl=%d pr=%g\n",pl,pp[pl]);
1743  prod0dualfprintf(debugfail>=3,fail_file,"NEWTON: %d : ijk=%d %d %d : %d %g\n",iter,ptrgeom->i,ptrgeom->j,ptrgeom->k,newtonstats.lntries,newtonstats.lerrx);
1744  radinvmodalt=*radinvmod; // default
1745  failreturnalt=failreturn; // default
1746 
1747  if(*eomtype==EOMCOLDGRMHD){// restore uu because this inversion assumes u=0 and sets u=0, but if cold valid then ok to keep u~0 and constant as long as fixups applied.
1748  pp[UU]=ppbackup[UU];
1749  if(ENTROPY>=0) pp[ENTROPY]=pp[UU];
1750  }
1751  // KORALTODO: now can check if actually did eomtype==EOMGRMHD or EOMENTROPYGRMHD or EOMCOLDGRMHD and apply correct error function if using QTYUMHD.
1752  // 4) now get consistent uu[] based upon actual final primitives.
1753  // Needed in case inversion reduced to entropy or cold.
1754  // Also needed to get correct UU[ENTROPY] if did full MHD inversion or get correct U[UU] if did entropy inversion, etc.
1755  get_state(pp, ptrgeom, q);
1756  primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
1757  // now have full primitives and full U including entropy and these are consistent with each other.
1758  // 5)
1759  // set alternative that doesn't keep any changes to iterated quantities
1760  PLOOP(pliter,pl) ppalt[pl] = pp[pl];
1761  PLOOP(pliter,pl) uualt[pl] = uu[pl];
1762  DLOOPA(iv) uualt[ru->irefU[iv]] = uubackup[ru->irefU[iv]];
1763  if(mtd->implicititer==QTYURAD || mtd->implicititer==QTYURADENERGYONLY || mtd->implicititer==QTYURADMOMONLY){
1764  radinvmodalt=0; // if iterating URAD, then ignore radinvmod==1 for alternative error but need to still use new primitives.
1765  if(failreturn==UTOPRIMGENWRAPPERRETURNFAILRAD) failreturnalt=UTOPRIMGENWRAPPERRETURNNOFAIL; // only change failure if only rad failure
1766  }
1767  }
1768 
1769 
1770 
1772  //
1773  // ENTROPYUMHD
1774  //
1776 
1777 
1778 
1780  // so iterating U[ENTROPY,U1,U2,U3]
1781  // FTYPE uuorig[NPR]; PLOOP(pliter,pl) uuorig[pl]=uu[pl];
1782  // 1) Do pure ENTROPYMHD inversion to get pmhd
1783  setgasinversionstuff(iter,whichcall,impeps,*errorabs,convabs,maxiter,&newtonstats,&checkoninversiongas,&checkoninversionrad);
1784  int doradonly=0; int eomtypetemp=EOMENTROPYGRMHD; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, &eomtypetemp, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1785  *nummhdinvsreturn++;
1786  radinvmodalt=*radinvmod; // default
1787  failreturnalt=failreturn; // default
1788  if(*eomtype==EOMCOLDGRMHD){// restore uu because this inversion assumes u=0 and sets u=0, but if cold valid then ok to keep u~0 and constant as long as fixups applied.
1789  pp[UU]=ppbackup[UU];
1790  if(ENTROPY>=0) pp[ENTROPY]=pp[UU];
1791  }
1792  // set eomtype! So for entire process for this cell, the entropy equations are used.
1793  *eomtype=EOMENTROPYGRMHD;
1794  // KORALTODO: now can check if actually did eomtypetemp==EOMENTROPYGRMHD or EOMCOLDGRMHD and apply correct error function in case reduced to cold MHD (maybe G=0?)
1795  // 2) get state (mhd and entropy are up-to-date, while rad is out-of-date, but fixed below)
1796  get_state(pp, ptrgeom, q);
1797  // 3) Compute U[UU] so have it for below (computes U[Ui,ENTROPY,RAD], but those not used or already known.)
1798  FTYPE uuentropy[NPR],uuentropyabs[NPR];
1799  primtoU(UNOTHING,pp,q,ptrgeom, uuentropy, uuentropyabs);
1800  uu[ENTROPY]=uuentropy[ENTROPY];
1801  uuabs[ENTROPY]=uuentropyabs[ENTROPY];
1802  // PLOOP(pliter,pl) if(pl==U1||pl==U2||pl==U3||pl==ENTROPY) pp[pl]=pporig[pl]; // get back U[ENTROPY,Ui] so no machine error introduced from u(p(u)) for actually known quantities that won't change due to fixups or anything. -- no, primitives from Utoprimgen might change things and act as Newton step fix.
1803  // 4) Get actual Urad [note uses UU not irefU that is ENTROPY for irefU[0]]
1804  DLOOPA(iv) uu[URAD0+iv] = uu0[URAD0+iv] - (uu[UU+iv]-uu0[UU+iv]);
1805  // 5) Do RAD-ONLY inversion
1806  int failreturn2; int doradonly2=1; failreturn2=Utoprimgen_failwrapper(doradonly2,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1807  // no need to concern with eomtype in RAD only case. i.e. eomtype won't change.
1808  if(failreturn2>failreturn) failreturn=failreturn2; // use worst case.
1809  // 6) now get consistent uu[] based upon actual final primitives.
1810  // Needed in case inversion reduced to entropy or cold or radiative inversion used fixups.
1811  get_state(pp, ptrgeom, q);
1812  primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
1813  // now have full primitives and full U including entropy and these are consistent with each other.
1814  // 7)
1815  // set alternative that doesn't keep any changes to iterated quantities
1816  PLOOP(pliter,pl) ppalt[pl] = pp[pl];
1817  PLOOP(pliter,pl) uualt[pl] = uu[pl];
1818  DLOOPA(iv) uualt[ru->irefU[iv]] = uubackup[ru->irefU[iv]];
1819  }
1820 
1821 
1822 
1824  //
1825  // ENTROPYPMHD
1826  //
1828 
1829 
1830  else if(mtd->implicititer==QTYENTROPYPMHD){
1831  // not setup
1832  myexit(92846534);
1833  }
1834 
1835 
1836 
1838  //
1839  // PMHD
1840  //
1842 
1843 
1844 
1846  // 0) Have pmhd={ug,uvel1,uvel2,uvel3}
1847  //
1848  // 0.5) trivially invert field
1849  PLOOPBONLY(pl) pp[pl] = uu0[pl];
1850  // set p[ENTROPY] in case evaluated as a diagnostic.
1851  if(ENTROPY>=0) pp[ENTROPY] = pp[UU];
1852  //
1853  // 1) get state of non-density related things (mhd state needed for q->ucon[TT] and primtoU) and Umhd, Uentropy [also computes Urad, but overwritten next and not expensive]
1854  get_state_norad_part1(pp, ptrgeom, q);
1855  //
1856  // 2) trivially invert to get rho
1857  pp[RHO]= uu0[RHO]/q->ucon[TT];
1858  //
1859  if(1){
1860  // Don't restrict rho or u_g except as by iteration catches. Don't restrict gamma or gammarad during iterations so can smoothly go out of bounds if required temporarily.
1861  // KORALTODO: SUPERGODMARK: causes many more high error - high iteration events. fixup1zone() has no radiation, so not consistent. But eventually applied! Is it due to limit_gamma() or density floors?
1862  // 3) Apply any fixups, like floors or limit_gamma's. Won't help reduce error, but even if solution with high fluid gamma, later apply limit_gamma, but then balance between fluid and radiation lost. So better to see as high error event than accurate high gamma event.
1863  int finalstepfixup=0; // treat as if not needing to diagnose, just act. KORALTODO: Although, Utoprimgen(finalstep) used to get change in fluid primitives.
1864  // Note, uu is old, but only used for diagnostics, and don't care about diagnostics in this stepping.
1865  FTYPE ppfixup[NPR],ppfloor[NPR],uufixup[NPR],prceiling[NPR];
1866  PLOOP(pliter,pl){
1867  ppfixup[pl]=ppfloor[pl]=pp[pl];
1868  uufixup[pl]=uu[pl];
1869  }
1870  // bsq is accurate using below
1871  FTYPE bsq; bsq_calc_fromq(ppfixup, ptrgeom, q, &bsq);
1872  // uu isn't exactly like pfixup here, but close enough
1873  set_density_floors_alt(ptrgeom, q, ppfixup, uu, bsq, ppfloor, prceiling);
1874  // fixup1zone(1,ppfloor,uufixup, ptrgeom,finalstepfixup); // too complicated for implicit stepping given how rare should be used.
1875  if(pp[RHO]<0.0) pp[RHO]=ppfloor[RHO]; // only fix RHO if really went negative. Not smooth, but avoids problems in difficult regimes.
1876 
1877  // limit_gamma(0,GAMMAMAX,GAMMAMAXRADIMPLICITSOLVER,pp,NULL,ptrgeom,0);
1878  // fix uu[RHO] to be consistent, since uu[RHO] used to get inverted scalars
1879  uu[RHO] = pp[RHO]*q->ucon[TT];
1880  // NOTEMARK: If uu0[RHO]<=0, then really no formal solution, but can still get solution to some error as long as adjust rho to be some "floor" value that is not unexpected when otherwise rho<0 would be implied and cause the radiation terms to be ill-defined or complex.
1881  // NOTEMARK: If happens to be on sub-step, then really not crucial and better to have had approximate solution for sub-step so perhaps final step can be regular with RHO and all terms. If only issue on sub-step, won't shown up in final diagnostics.
1882  }
1883  //
1884  // 4) Invert other scalars (only uses uu[RHO], not pp[RHO])
1885  extern int invert_scalars1(struct of_geom *ptrgeom, FTYPE *Ugeomfree, FTYPE *pr);
1886  invert_scalars1(ptrgeom, uu,pp);
1887  //
1888  // save final fixed-up pp's
1889  FTYPE pporig[NPR]; PLOOP(pliter,pl) pporig[pl]=pp[pl];
1890  // NOW all MHD pp's are set and backed-up
1891  //
1892  // 5) Do rest of get_state that used rho, and other scalars, in case used.
1893  // This computes pressure (as required for T^t_\mu) and entropy (as required for primtoflux_nonradonly below for entropy flux)
1894  // KORALTODO: Although, don't need entropy if doing mtd->implicitferr==UMHD
1895  get_state_norad_part2(needentropy, pp, ptrgeom, q); // where entropy would be computed
1896 
1897  //
1898  // 6) Compute Umhd and Uentropy (keeps Urad as zero, but Urad set next)
1899  //primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
1900  extern int primtoflux_nonradonly(int needentropy, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
1901  FTYPE uumhd[NPR],uumhdabs[NPR];
1902  primtoflux_nonradonly(needentropy,pp,q,TT,ptrgeom, uumhd, uumhdabs); // anything not set is set as zero, which is rad.
1903  PLOOP(pliter,pl) if(!RADFULLPL(pl)) uu[pl]=uumhd[pl];
1904  PLOOP(pliter,pl) if(!RADFULLPL(pl)) uuabs[pl]=uumhdabs[pl];
1905  // primtoflux_nonradonly(1,pp,q,TT,ptrgeom, uu, uuabs); // doesn't actually compute entropy again, just multiplies existing things.
1906  // if(needentropy==0) uu[ENTROPY]=sqrt(-1.0);
1907 
1908  // 7) Get actual Urad(G) via energy conservation (correct even if using entropy as error function, because just computed correct U[ENTROPY] consistent with U[UU].
1909  // KORALNOTE: uu set by p->uu, which has an error of order machice precision. So even if primitives didn't change, uu-uu0 can be order machine precision. So when fluid uu>>rad uu, this can lead to the below giving huge radiation changes even if actually fluid background is not changing.
1910  DLOOPA(iv) uu[ru->iotherU[iv]] = uu0[ru->iotherU[iv]] - (uu[ru->irefU[iv]]-uu0[ru->irefU[iv]]);
1911  DLOOPA(iv) uuabs[ru->iotherU[iv]] = fabs(uu0[ru->iotherU[iv]]) + fabs(uu[ru->irefU[iv]]) + fabs(uu0[ru->irefU[iv]]);
1912 
1913  //
1914  // 8) Do RAD-ONLY Inversion (eomtype not used)
1915  int whichcapnew;
1916  if(USECAPTYPEFIX2FORF1 && whichcall==FIMPLICITCALLTYPEF1) whichcapnew=CAPTYPEFIX2;
1917  else if(USECAPTYPEFIX2FORFINALCHECK && whichcall==FIMPLICITCALLTYPEFINALCHECK) whichcapnew=CAPTYPEFIX2;
1918  else whichcapnew=whichcap; // for jacobian, likely to be CAPTYPEFIX2 anyways.
1919  int doradonly=1; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcapnew, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
1920  radinvmodalt=*radinvmod; // default
1921  failreturnalt=failreturn; // default
1922  // no need to concern with eomtype in RAD only case. i.e. eomtype won't change.
1923  // if(*radinvmod>0) dualfprintf(fail_file,"radinvmodinside=%d whichcall=%d : u=%g Erf=%g\n",*radinvmod,whichcall,pp[UU],pp[PRAD0]);
1924 
1925 
1926 #if(0)
1927  // deal with Erf<0 and possibly gammarad caps or E_r<0 issues
1928  if(iter<mtd->BEGINNORMALSTEPS+4 && pp[PRAD0]<10.0*ERADLIMIT && ppbackup[PRAD0]>10.0*ERADLIMIT){
1929  // then can play with Erf in case negative E_r to avoid bad NR due to floor on Erf.
1930  PLOOP(pliter,pl) if(RADFULLPL(pl)) pp[pl]=ppbackup[pl]; // only concern is error might coincidentally be small
1931  dualfprintf(fail_file,"Caught\n");
1932  }
1933  if(myid==8){
1934  dualfprintf(fail_file,"bob: iter=%d (%d) %g %g (%g)\n",iter,mtd->BEGINNORMALSTEPS+4,pp[PRAD0],ppbackup[PRAD0],10.0*ERADLIMIT);
1935  }
1936 #endif
1937 
1938  //
1939  // 9) Get consistent RAD state
1940  // only changes radiation state, not fluid state, but keeps old q's for fluid state for next step.
1941  get_state_radonly(pp, ptrgeom, q);
1942  //
1943  // fix-up primitives to avoid violent steps in temperature
1944  //
1945  // 10) Get new uu[RAD] since original uu[RAD]->pp[RAD] might have had fixups applied and then uu[RAD] no longer consistent.
1946  // This violates total energy conservation in favor of consistency of radiative quantities between pp and uu
1947  // primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
1948  extern int primtoflux_radonly(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
1949  FTYPE uurad[NPR],uuradabs[NPR];
1950  primtoflux_radonly(pp,q,TT,ptrgeom, uurad,uuradabs); // all non-rad stuff is set to zero.
1951  // write new uurad's to uu
1952  PLOOP(pliter,pl) if(RADFULLPL(pl)) uu[pl]=uurad[pl];
1953  PLOOP(pliter,pl) if(RADFULLPL(pl)) uuabs[pl]=uuradabs[pl];
1954  //
1955  // 11) Recover actual iterated pmhd to avoid machine related differences between original pp and pp(U(pp)) for pmhd quantities
1956  // This assumes that iterated pmhd is optimal and not modified except by iteration by Newton step, which is currently true.
1957  // This gives machine error priority to mhd primitives rather than mhd U's.
1958  // below not necessary since don't overwrite pp[non-rad]
1959  //PLOOP(pliter,pl) if(!RADFULLPL(pl)) pp[pl]=pporig[pl];
1960  //
1961  // 12) overwrite any setting of uu[B1,B2,B3], so machine accurate field
1962  PLOOPBONLY(pl) uu[pl]=pp[pl];
1963  //
1964  // now have full primitives (pp) and full U (uu) including entropy and these (pp and uu) are fully consistent with each other.
1965 
1966 
1967  extern int invert_scalars2(struct of_geom *ptrgeom, FTYPE *Ugeomfree, struct of_state *q, FTYPE *pr);
1968  invert_scalars2(ptrgeom, uu,q,pp);
1969 
1970 
1971  // 13)
1972  // set alternative that doesn't keep any changes to iterated quantities
1973  PLOOP(pliter,pl) ppalt[pl] = pp[pl];
1974  DLOOPA(iv) ppalt[ru->irefU[iv]] = ppbackup[ru->irefU[iv]];
1975  PLOOP(pliter,pl) uualt[pl] = uu[pl];
1976 
1977  }
1978 
1979 
1980 
1982  //
1983  // PRAD
1984  //
1986 
1987 
1988 
1989  else if(mtd->implicititer==QTYPRAD || mtd->implicititer==QTYPRADENERGYONLY || mtd->implicititer==QTYPRADMOMONLY){
1990  // 0.5) trivially invert field
1991  PLOOPBONLY(pl) pp[pl] = uu0[pl];
1992  // Have prad={Erf,uradvel1,uradvel2,uradvel3}
1993  // 1) get state (rad state needed for mhd_calc_rad, while old mhd state needed to estimate uu[ENTROPY] below)
1994  get_state(pp, ptrgeom, q);
1995  // 2) Compute Urad[prad0,uradcon,uradcov] [also computes old Umhd and old Uentropy, but not used]
1996  FTYPE uurad[NPR],uuradabs[NPR];
1997  primtoU(UNOTHING,pp,q,ptrgeom, uurad, uuradabs);
1998  PLOOP(pliter,pl) if(RADFULLPL(pl)){
1999  uu[pl]=uurad[pl];
2000  uuabs[pl]=uuradabs[pl];
2001  }
2002  // 3) Get actual Umhd(G) via energy conservation:
2003  FTYPE Gddt[NDIM]; DLOOPA(iv) Gddt[iv]=(uu[ru->irefU[iv]]-uu0[ru->irefU[iv]]);
2004  DLOOPA(iv) uu[ru->iotherU[iv]] = uu0[ru->iotherU[iv]] - Gddt[iv];
2005  // uu0[RHO] doesn't change
2006  // 4) Estimate U[ENTROPY](G) using old rho,u
2007  // UNSURE what to do, since blows up either way:
2008  // FTYPE GS=0.0; DLOOPA(iv) GS += (-q->ucon[iv]*(ru->signgd2)*( (ru->signgd7)*Gddt[iv]))/(Tgaslocal+TEMPMIN); // more accurate than just using entropy from pp and ucon[TT] from state from pp.
2009  FTYPE GS=0.0;
2010  FTYPE Tgaslocal=0.0,Tradlocal=0.0;
2011  if(0){
2012  Tgaslocal=compute_temp_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pp[RHO],pp[UU]);
2013  DLOOPA(iv) GS += (-q->ucon[iv]*(ru->signgd2)*( (ru->signgd7)*Gddt[iv]))/(Tgaslocal+TEMPMIN); // more accurate than just using entropy from pp and ucon[TT] from state from pp.
2014  }
2015  else{
2016  // Get GS completely consisent with primitives, in case using entropy error function, because then shouldn't use Gddt[TT] related to energy equation.
2017  // Below rad inv may not be completely necessary, but not too expensive, so ok.
2018  int computestate=0; // already computed above
2019  int computeentropy=1;
2020  koral_source_rad_calc(computestate,computeentropy,pp, ptrgeom, Gdpl, Gdplabs, NULL, &Tgaslocal, &Tradlocal, q);
2021  GS = - (ru->signgd4) * localdt * Gdpl[ENTROPY]/(ru->signgd6); // so uu = uu0 + signgd6*GS is consistent with how Gdpl included in error function later.
2022  }
2023  uu[ENTROPY] = uu0[ENTROPY] + (ru->signgd6)*GS;
2024  // 5) Invert to get pmhd (also does rad inversion, but not expensive so ok)
2025  setgasinversionstuff(iter,whichcall,impeps,*errorabs,convabs,maxiter,&newtonstats,&checkoninversiongas,&checkoninversionrad);
2026  int doradonly=0; failreturn=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, eomtype, whichcap, EVOLVEUTOPRIM, UNOTHING, uu, q, ptrgeom, dissmeasure, pp, &newtonstats);
2027  *nummhdinvsreturn++;
2028  radinvmodalt=*radinvmod; // default
2029  failreturnalt=failreturn; // default
2030  if(*eomtype==EOMCOLDGRMHD){// restore uu because this inversion assumes u=0 and sets u=0, but if cold valid then ok to keep u~0 and constant as long as fixups applied.
2031  pp[UU]=ppbackup[UU];
2032  if(ENTROPY>=0) pp[ENTROPY]=pp[UU];
2033  }
2034  // KORALTODO: now can check if actually did eomtype==EOMGRMHD or EOMENTROPYGRMHD or EOMCOLDGRMHD and apply correct error function
2035  // 6) Recover actual iterated prad to avoid machine related differences between original pp and pp(U(pp)) for prad quantities
2036  // This assumes that iterated prad is optimal and not modified except by iteration by Newton step
2037  PLOOP(pliter,pl) if(RADFULLPL(pl)) pp[pl]=ppbackup[pl];
2038  // 7) Get consistent Urad [also computes Umhd and Uentropy, which is ok]
2039  get_state(pp, ptrgeom, q);
2040  primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
2041  // 8) overwrite any setting of uu[B1,B2,B3], so machine accurate field
2042  PLOOPBONLY(pl) uu[pl]=pp[pl];
2043  // now have full primitives and full U including entropy and these are consistent with each other.
2044  // 9)
2045  // set alternative that doesn't keep any changes to iterated quantities
2046  PLOOP(pliter,pl) ppalt[pl] = pp[pl];
2047  DLOOPA(iv) ppalt[ru->irefU[iv]] = ppbackup[ru->irefU[iv]];
2048  PLOOP(pliter,pl) uualt[pl] = uu[pl];
2049  }
2050 
2051 
2052 
2053 
2054 
2055 
2056 
2057 
2058 #if(MODEMETHOD==MODEENERGY ||MODEMETHOD==MODEENTROPY ||MODEMETHOD==MODESWITCH) // currently only ones that allow change
2059 
2060  //
2061  // check which baseitermethod we should really be using based upon any inversions done above
2062  //
2064  // only check if not in Jacobian or final check
2065  if(allowbaseitermethodswitch && whichcall==FIMPLICITCALLTYPEF1){//FIMPLICITCALLTYPEJAC
2066 
2067  int doswitchbaseitermethod=0;
2068  FTYPE rdU[NPR];
2069  // PLOOP(pliter,pl) rdU[pl]=Gallabs[pl]/uuallabs[pl];
2070  // Note that we use uu-uu0 since that's exactly what's pushed into other non-iterated set of equations.
2071  FTYPE uuallabs1;
2072  PLOOP(pliter,pl){
2073  uuallabs1 = THIRD*(fabs(uuabs[pl]) + fabs(uu[pl]) + fabs(uu0[pl]));
2074  rdU[pl]=(uu[pl]-uu0[pl])/uuallabs1;
2075  }
2076  // if dU[UU] changes relatively near machine precision, then could be fake change induced by machine precision errors. Then actual real evolution of URAD? would be destroyed by those machine errors.
2077  // For iter=1, using initial guess's uu. But by second iteration, have used Jacobian to move iterates. If dU[UU]/U[UU] near machine precision but dU[URAD0]/U[URAD0] far from it, then should use radiation iterate.
2078  if(iter>1){
2079  if(rdU[UU]<rdU[URAD0] && IMPMHDTYPEBASE(*baseitermethod)==1){
2080  prod0dualfprintf(debugfail>=3,fail_file,"Should switch base to QTYURAD or QTYPRAD\n");
2081  }
2082  if(rdU[UU]>rdU[URAD0] && (*baseitermethod==QTYURAD||*baseitermethod==QTYPRAD)){
2083  prod0dualfprintf(debugfail>=3,fail_file,"Should switch base to QTYPMHD\n");
2084  }
2085  }
2086  if(pp[URAD0]<10.0*ERADLIMIT && IMPMHDTYPEBASE(*baseitermethod)==1){
2087  prod0dualfprintf(debugfail>=3,fail_file,"Should switch base to QTYURAD or QTYPRAD: Erf=%21.15g<10*%21.15g baseitermethod=%d\n",pp[URAD0],ERADLIMIT,*baseitermethod);
2088  if(1){
2089  // then Erf dropped-out. Probably because using QTYPMHD and too big change
2090  *baseitermethod=QTYPRAD; // prad safest and fastest
2091  //*baseitermethod=QTYURAD; // URAD somehow more robust (e.g. on RADTUBE PRAD methods fails a few times if switched from QTYPMHD, but fails more if used directly!)
2092  doswitchbaseitermethod=1;
2093  PLOOP(pliter,pl){
2094  pp[pl] = ppprev[pl]; // revert primitives from old primitive iteration to new primitive iteration
2095  uu[pl] = uuprev[pl]; // start with previous uu's before any pp->uu calculations
2096  }
2097  // get state since not synched with q necessarily
2098  get_state(pp, ptrgeom, q);
2099  primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
2100  //*q=qbackup; // revert to q before any pp->q calculations
2101  *radinvmod=radinvmodbackup; // revert to previous radinvmod
2102  }
2103  else{
2104  // problem with switching for RADTUBE, so just report if want. If had backup method that was radiation iterate, then might want to break, but not always as QTYPMHD method can recover. So just stick with normal backup procedure...?
2105  }
2106  }
2107  if(pp[UU]<10.0*UUMINLIMIT && (*baseitermethod==QTYURAD||*baseitermethod==QTYPRAD)){
2108  // Then u_g dropped-out. Probably because iteration radiation quantity
2109  prod0dualfprintf(debugfail>=3,fail_file,"Should switch base to QTYMHD: ug=%21.15g\n",pp[UU]);
2110  }
2111 
2112  if(doswitchbaseitermethod){
2113  // in case required, change settings
2114  define_method(iter, eomtype, itermode, *baseitermethod, fracenergy, dissmeasure, &mtd);
2115  get_refUs(&mtd, &ru);
2116  }
2117  }
2118 #endif
2119 
2120 
2121 
2122 
2123 
2124 
2126  //
2127  // At this point, must have pp, uu, uuabs, and q all consistent and defined
2128  //
2130 
2131 
2132 
2133 
2134 
2135 
2137  // get 4-force for all pl due to radiation as due to pp[uu]
2139  int computestate=0;// already computed above
2140  int computeentropy=needentropy;
2141  FTYPE chieff;
2142  FTYPE tautot,tautotmax;
2143  koral_source_rad_calc(computestate,computeentropy,pp, ptrgeom, Gdpl, Gdplabs, &chieff, &Tgas, &Trad, q);
2144  calc_tautot_chieff(pp, chieff, ptrgeom, q, &tautot, &tautotmax);
2145  *tautotmaxreturn=tautotmax;
2146 
2147 
2148 
2149 
2150 
2152  // GET ERROR FUNCTION
2153  //
2154  // NOTEMARK: Error is normalized by sum of any terms that can be formed separately as an absolute magnitude. For gas, error *includes* MA+EM but not rest-mass (at least when REMOVERESTMASSFROMUU=2 is set, which is default). While one might think error should only include MA due to MA<->RAD force G, the force G affects the full T and changes the (e.g.) EM energy flux by changing the velocity. So even if RAD only directly affects particles=MA, that MA involves changes in velocity that affects EM as well, so indirectly RAD affects EM. E.g., it's possible that MA energy flux doesn't change at all, but RAD<->EM conversion occurs. E.g., just as scattering provides force from gas to radiation, velocity changes provide force between MA and EM. So keep uu[Ux] full MA+EM in normalization of error.
2155  // NOTEMARK: Of course, possible field is background uniform and strong and has no force role at all, in which case should have just MA in error norm.
2156  // NOTEMARK: But of course, if (say) b^2/rho>>1, then can't expect to get rho very accurate anyways, so focus on total error so that as b^2/rho gets bigger, error in rho gets worse. However, error in velocity will still be preserved since those appear as separate error terms (i.e. uu[U1-U3]).
2157  //
2159 
2160  // prepare for error or explicit step
2161  FTYPE sign[NPR];
2162  PLOOP(pliter,pl){
2163  sign[pl]=ru->signgd2;
2164  }
2165  if(ENTROPY>=0){
2166  pl=ENTROPY;
2167  sign[pl]=ru->signgd4;
2168  }
2169 
2170 
2171  FTYPE extrafactor[NPR];
2172  PLOOP(pliter,pl){
2173  extrafactor[pl]=1.0;
2174  }
2175  if(ENTROPY>=0){
2176  pl=ENTROPY;
2177  // replace original equation with dS*T equation
2178  // error function is T*dS so no actual division by T. Found in mathematica that this works best in difficult precision cases.
2179  extrafactor[pl]=fabs(Tgas)+TEMPMIN;
2180  }
2181 
2182  // get f, uuallabs, Gallabs, and fnorm
2183  // also get falt that uses (in case iterated) originally iterated value of uu -- instead of post-inversion modified version that would be consistent with primitives.
2184  FTYPE falt[NPR];
2185  FTYPE uuallabs[NPR]={0.0},Gallabs[NPR]={0.0};
2186  //
2187  PLOOP(pliter,pl){
2188  f[pl] = ((uu[pl] - uu0[pl]) + (sign[pl] * localdt * Gdpl[pl]))*extrafactor[pl];
2189 
2190  falt[pl] = ((uualt[pl] - uu0[pl]) + (sign[pl] * localdt * Gdpl[pl]))*extrafactor[pl];
2191 
2192  // get error normalization that involves actual things being differenced
2193  // KORALNOTE: Use Gdplabs to ensure absolute value over more terms in source in case coincidental cancellation without physical significance.
2194  uuallabs[pl] = THIRD*(fabs(uuabs[pl]) + fabs(uu[pl]) + fabs(uu0[pl]))*extrafactor[pl];
2195  Gallabs[pl] = fabs(sign[pl] * localdt * Gdplabs[pl])*extrafactor[pl];
2196  fnorm[pl] = uuallabs[pl] + Gallabs[pl];
2197  }
2198 
2199 
2200 
2201  if(whichcall!=FIMPLICITCALLTYPEJAC){
2203  //
2204  // get single number that measures error for iterated quantities
2205  // only do if using error, which don't for Jacobian
2206  //
2208  *convreturn=f_error_check(showmessages, showmessagesheavy, iter, conv, convabs, realdt, dimtypef,*eomtype , *radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,pp,piin,f,fnorm,freport,Uiin,uu0,uu,ptrgeom,errorabs,errorallabs,whicherror,mtd,ru);
2209  }
2210 
2211 
2212 
2213 
2214 
2215 
2216  // get fractional change in |R^t_t| as estimate from \tau, as soft backup to Gdplabs
2217  FTYPE ratchangeRtt;
2218  if(1){
2219  if(whichcall==FIMPLICITCALLTYPEF1){//FIMPLICITCALLTYPEJAC)
2220  // ratchangeRtt1 covers generic opacity control of G_t vs R^t_t
2221  FTYPE ratchangeRtt1=calc_approx_ratchangeRtt(q, chieff, realdt);
2222 
2223  pl=URAD0;
2224  FTYPE uuallabsURAD0 = THIRD*(fabs(uuabs[pl]) + fabs(uu[pl]) + fabs(uu0[pl]));
2225  FTYPE ratchangeRtt2=fabs(Gdplabs[pl]*realdt)/uuallabsURAD0;
2226 
2227  pl=UU;
2228  FTYPE uuallabsUU = THIRD*(fabs(uuabs[pl]) + fabs(uu[pl]) + fabs(uu0[pl]));
2229  FTYPE ratchangeRtt3=fabs(Gdplabs[pl]*realdt)/uuallabsUU;
2230 
2231  // take bigger of change to be most conservative to force most implicit approach
2232  ratchangeRtt = MAX(MAX(ratchangeRtt1,ratchangeRtt2),ratchangeRtt3);
2233 
2234  // get_dtsub(int method, pp, q, uu0, uu, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gdpl, FTYPE chi, FTYPE *Gdplabs, struct of_geom *ptrgeom, FTYPE *dtsub)
2235  }
2236  }
2237 
2238 
2239 
2240 
2241 
2242 
2243 
2244  // try doing 1 explicit step when doing first implicit iteration.
2245  // Needed if rho,u<<urad and want to resolve regions that are optically thin like the jet. Else would have to have overall small error and that woudld be slower.
2246  int didexplicit=0;
2247 #if(TRYFIRSTEXPLICIT)
2248  if(whichcall==FIMPLICITCALLTYPEF1){//FIMPLICITCALLTYPEJAC)
2249 
2250  if(iter==1 && f1iter==0 && (mtd->implicititer==QTYPMHD || mtd->implicititer==QTYPMHDENERGYONLY || mtd->implicititer==QTYPMHDMOMONLY)){ // GODMARK: Not currently working for other QTY methods like QTYURAD.
2251 
2252 
2253 
2254 
2255 
2256 #if(0)
2257  // initial
2258  FTYPE Gdpli[NPR]={0.0},Gdplabsi[NPR]={0.0}, Tgasi={0.0},Tradi={0.0};
2259  FTYPE ppi[NPR],uui[NPR];
2260  FTYPE uuabsi[NPR]={0.0};
2261  PLOOP(pliter,pl) uuabsi[pl]=uuabs[pl];
2262  FTYPE chieffi=0.0;
2263  FTYPE extrafactori[NPR];
2264  FTYPE fi[NPR]={0.0},fnormi[NPR]={0.0};
2265  FTYPE uuallabsi[NPR]={0.0},Gallabsi[NPR]={0.0};
2266  FTYPE errorabsi=BIG,errorallabsi=BIG;
2267  FTYPE freporti[NPR];
2268  int convreturni;
2269  int didinitial=0;
2270  struct of_state qi;
2271  qi=*q;
2272 
2273  if(1){
2274  // begin
2275  PLOOP(pliter,pl) ppi[pl]=piin[pl];
2276  PLOOP(pliter,pl){
2277  if(pl>=UU && pl<=U3 || pl>=URAD0 && pl<=URAD3) uui[pl]=Uiin[pl];
2278  else uui[pl]=uu0[pl];
2279  }
2280  //PLOOP(pliter,pl) ppi[pl]=pp[pl];
2281  // PLOOP(pliter,pl) uui[pl]=uu0[pl];
2282 
2283  int failreturni=1;
2284  if(1){
2285  setgasinversionstuff(iter,whichcall,impeps,*errorabs,convabs,maxiter,&newtonstats,&checkoninversiongas,&checkoninversionrad);
2286  //newtonstats.tryconv=MIN(1E-6,convabs)*1E-2;
2287  // newtonstats.tryconvultrarel=MIN(1E-6,convabs)*1E-2;
2288  // newtonstats.maxiter=20;
2289  newtonstats.tryconv=1E-12;
2290  newtonstats.tryconvultrarel=1E-12;
2291  newtonstats.maxiter=40;
2292  int eomtypei=*eomtype;
2293  int radinvmodi;
2294  int doradonlyi=0; failreturni=Utoprimgen_failwrapper(doradonlyi,&radinvmodi,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, &eomtypei, whichcap, EVOLVEUTOPRIM, UNOTHING, uui, &qi, ptrgeom, dissmeasure, ppi, &newtonstats);
2295  // *nummhdinvsreturn++;
2296  // completed inversion so that ppi=ppi(uu0)
2297  }
2298 
2299  if(failreturni!=UTOPRIMGENWRAPPERRETURNFAILMHD){
2300  didinitial=1;
2301 
2302  // get other things usually needed at end of f_implicit()
2303  get_state(ppi, ptrgeom, &qi);
2304 
2305  koral_source_rad_calc(computestate,computeentropy,ppi, ptrgeom, Gdpli, Gdplabsi, &chieffi, &Tgasi, &Tradi, &qi);
2306  // FTYPE tautoti,tautotmaxi;
2307  // calc_tautot_chieff(ppi, chieffi, ptrgeom, q, &tautoti, &tautotmaxi);
2308 
2309  PLOOP(pliter,pl){
2310  extrafactori[pl]=1.0;
2311  }
2312  // get new extrafactor for entropy
2313  if(ENTROPY>=0){
2314  pl=ENTROPY;
2315  extrafactori[pl]=fabs(Tgasi)+TEMPMIN;
2316  }
2317  PLOOP(pliter,pl){
2318  fi[pl] = ((uui[pl] - uu0[pl]) + (sign[pl] * localdt * Gdpli[pl]))*extrafactori[pl];
2319 
2320  uuallabsi[pl] = THIRD*(fabs(uuabsi[pl]) + fabs(uui[pl]) + fabs(uu0[pl]))*extrafactori[pl];
2321  Gallabsi[pl] = fabs(sign[pl] * localdt * Gdplabsi[pl])*extrafactori[pl];
2322  fnormi[pl] = uuallabsi[pl] + Gallabsi[pl];
2323 
2324  }
2325 
2326  convreturni=f_error_check(showmessages, showmessagesheavy, iter, conv, convabs, realdt, dimtypef,*eomtype , *radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,ppi,piin,fi,fnormi,freporti,Uiin,uu0,uui,ptrgeom,&errorabsi,&errorallabsi,whicherror);
2327  }
2328  }
2329 #endif
2330 
2331 
2332 
2333 
2334 
2335 
2336 
2337  // then do explicit step
2338  // explicit step using explicit-like dt
2339  //FTYPE idtsub0=SMALL+fabs(ratchangeRtt)/realdt;
2340  //FTYPE explicitdt=MIN(localdt,1.0/idtsub0);
2341  FTYPE uue[NPR],uueabs[NPR],ppe[NPR];
2342  FTYPE errorabse=BIG,errorallabse=BIG;
2343  FTYPE fe[NPR]={0.0},fnorme[NPR]={0.0};
2344  FTYPE uuallabse[NPR]={0.0},Gallabse[NPR]={0.0};
2345  FTYPE freporte[NPR];
2346  int convreturne;
2347  FTYPE Gdple[NPR]={0.0},Gdplabse[NPR]={0.0}, Tgase={0.0},Trade={0.0};
2348  // FTYPE uuabse[NPR]={0.0};
2349  FTYPE chieffe=0.0;
2350  FTYPE extrafactore[NPR];
2351  struct of_state qe;
2352  qe=*q;
2353 
2354  if(1){
2355  FTYPE explicitdt=localdt;
2356  PLOOP(pliter,pl){
2357  ppe[pl] = pp[pl];
2358  uue[pl] = -((0- uu0[pl]) + (sign[pl] * explicitdt * Gdpl[pl])); // uses Gdpl[pp(uu)]
2359  uueabs[pl] = uuabs[pl]; // estimate
2360  }
2361 
2362 
2363  setgasinversionstuff(iter,whichcall,impeps,*errorabs,convabs,maxiter,&newtonstats,&checkoninversiongas,&checkoninversionrad);
2364  //newtonstats.tryconv=MIN(1E-6,convabs)*1E-2;
2365  //newtonstats.tryconvultrarel=MIN(1E-6,convabs)*1E-2;
2366  //newtonstats.maxiter=20;
2367  if(maxiter<=1){
2368  newtonstats.tryconv=1E-1;
2369  newtonstats.tryconvultrarel=1E-1;
2370  newtonstats.maxiter=1;
2371  newtonstats.extra_newt_iter=0;
2372  newtonstats.extra_newt_iter_ultrarel=0;
2373  }
2374  else{
2375  newtonstats.tryconv=(1E3*NUMEPSILON);
2376  newtonstats.tryconvultrarel=(5*NUMEPSILON);
2377  newtonstats.maxiter=100;
2378  newtonstats.extra_newt_iter=2;
2379  newtonstats.extra_newt_iter_ultrarel=2;
2380  }
2381  int eomtypee=*eomtype;
2382  int radinvmode;
2383  int finalstepe=0;
2384  int doradonly=0; int failreturne=Utoprimgen_failwrapper(doradonly,&radinvmode,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstepe, &eomtypee, whichcap, EVOLVEUTOPRIM, UNOTHING, uue, &qe, ptrgeom, dissmeasure, ppe, &newtonstats);
2385  // if switches to entropy (*eomtype=EOMGRMHD -> eomtypee=EOMENTROPYGRMHD), then uue won't be changed, but ppe will be entropy inversion solution. So below error test using uue and Gple uses uue from energy and Gple from entropy primitives, which is fine because Gpl still computed as perfectly conservative and uue still conservative. So good error check.
2386  // However, final primitives (ppe) not consistent with conserved (uue), like normally would be.
2387  // However, if really error ended up small, then would drop out of f1 loop and still do FINALCHECK that would recompute f1 and ensure primitives and conserves are consistent *and* based upon original emptype because Utoprimgen not used. At that point, entropy gas solution would be used to compute UUgas and then radiation would be computed as UUrad=uu0rad-dUgas with dUgas=uu0-UUgas, so that radiation bears brunt of error of using entropy in gas -- but total energy conserved. In optically thick or high radiation regions, this is fine. In optically thin regions or gas-dominated regions, this is an issue -- acts like effective opacity even though no opacity -- like numerical opacity. So this acts like automatic borrow operation.
2388 
2389  //*nummhdinvsreturn++;
2390  // completed explicit step
2391 
2392  // get MHD state
2393  get_state_norad_part1(ppe, ptrgeom, &qe);
2394  get_state_norad_part2(needentropy, ppe, ptrgeom, &qe); // where entropy would be computed
2395 
2396  // get accurate UMHD[pmhd] to avoid inversion inaccuracies for MHD inversion part
2397  extern int primtoflux_nonradonly(int needentropy, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
2398  FTYPE uumhd[NPR],uumhdabs[NPR];
2399  primtoflux_nonradonly(needentropy,ppe,&qe,TT,ptrgeom, uumhd, uumhdabs); // anything not set is set as zero, which is rad.
2400  PLOOP(pliter,pl) if(!RADFULLPL(pl)) uue[pl]=uumhd[pl];
2401  PLOOP(pliter,pl) if(!RADFULLPL(pl)) uueabs[pl]=uumhdabs[pl];
2402 
2403 
2404 
2405  didexplicit=0;
2406  if(failreturne!=UTOPRIMGENWRAPPERRETURNFAILMHD){
2407  didexplicit=1;
2408 
2409 
2410 #if(1)
2411  // might think not needed because pgas(entropy) and uue(energy) will be used below in error and error used will be for eomtype so any error that exists will be seen in use of Gpl(pgas(entropy) as compared to uue and uu0 and that Gpl. So good error estimate. No use of rad errors for whicherror=0, but *is* used for whicherror=1
2412 
2414  // then ensure total energy conservation version of primitives obtained here, and total consistent p/uu used in error estimate
2415  // matters to get whicherror=1 error estimate valid/constent.
2416  DLOOPA(iv) uue[ru->iotherU[iv]] = uu0[ru->iotherU[iv]] - (uue[ru->irefU[iv]]-uu0[ru->irefU[iv]]);
2417  DLOOPA(iv) uuabs[ru->iotherU[iv]] = fabs(uu0[ru->iotherU[iv]]) + fabs(uue[ru->irefU[iv]]) + fabs(uu0[ru->irefU[iv]]); // assume uuabs ok as same
2418 
2419  int eomtypee2=*eomtype; // back to original, but doing radiation below so doesn't matter.
2420  int radinvmode2;
2421  int doradonly2=1; int failreturne2=Utoprimgen_failwrapper(doradonly2,&radinvmode2,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstepe, &eomtypee2, whichcap, EVOLVEUTOPRIM, UNOTHING, uue, &qe, ptrgeom, dissmeasure, ppe, &newtonstats);
2422  // if radinvmode==0 and radinvmode2!=0, should we abort explicit?
2423  // as long as radinvmode2==0, then all uu and pp's are now consistent
2424 
2425  }
2426 #endif
2427 
2428  // get other things usually needed at end of f_implicit()
2429  // get_state(ppe, ptrgeom, &qe);
2430 
2431  // ensure uue is exactly consistent with ppe despite inversion inaccuracies.
2432  // primtoU(UNOTHING,ppe,&qe,ptrgeom, uue, uueabs);
2433 
2434  extern int primtoflux_radonly(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
2435  FTYPE uurad[NPR],uuradabs[NPR];
2436  primtoflux_radonly(ppe,&qe,TT,ptrgeom, uurad,uuradabs); // all non-rad stuff is set to zero.
2437  // write new uurad's to uu
2438  PLOOP(pliter,pl) if(RADFULLPL(pl)) uue[pl]=uurad[pl];
2439  PLOOP(pliter,pl) if(RADFULLPL(pl)) uueabs[pl]=uuradabs[pl];
2440 
2441 
2442 
2443  koral_source_rad_calc(computestate,computeentropy,ppe, ptrgeom, Gdple, Gdplabse, &chieffe, &Tgase, &Trade, &qe);
2444 
2445  PLOOP(pliter,pl){
2446  extrafactore[pl]=1.0;
2447  }
2448  // get new extrafactor for entropy
2449  if(ENTROPY>=0){
2450  pl=ENTROPY;
2451  extrafactore[pl]=fabs(Tgase)+TEMPMIN;
2452  }
2453 
2454  PLOOP(pliter,pl){
2455  fe[pl] = ((uue[pl] - uu0[pl]) + (sign[pl] * localdt * Gdple[pl]))*extrafactore[pl];
2456 
2457  uuallabse[pl] = THIRD*(fabs(uueabs[pl]) + fabs(uue[pl]) + fabs(uu0[pl]))*extrafactore[pl];
2458  Gallabse[pl] = fabs(sign[pl] * localdt * Gdplabse[pl])*extrafactore[pl];
2459  fnorme[pl] = uuallabse[pl] + Gallabse[pl];
2460  }
2461 
2462  convreturne=f_error_check(showmessages, showmessagesheavy, iter, conv, convabs, realdt, dimtypef,*eomtype , *radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,ppe,piin,fe,fnorme,freporte,Uiin,uu0,uue,ptrgeom,&errorabse,&errorallabse,whicherror,mtd,ru);
2463  }
2464  else{
2465  // if(ptrgeom->i==8 && ptrgeom->j==10) dualfprintf(fail_file,"explicitnotwork\n");
2466  }
2467  }
2468 
2469 
2470 
2471  // choose best guess
2472  // if(fabs(errorallabse)<fabs(*errorallabs) && fabs(errorallabsi)>fabs(errorallabse)){
2473  //if(errorallabse<0.1 && fabs(errorallabse)<fabs(*errorallabs) && fabs(errorallabsi)>fabs(errorallabse)){
2474  //if(0){
2475  if(fabs(errorallabse)<fabs(*errorallabs)){
2476  // if(ptrgeom->i==8 && ptrgeom->j==10) dualfprintf(fail_file,"explicitchosenasguess: %21.15g over %21.15g and %21.15g\n",errorallabse,*errorallabs,errorallabsi);
2477  PLOOP(pliter,pl){
2478  // if(ptrgeom->i==8 && ptrgeom->j==10) dualfprintf(fail_file,"fr=%21.15g %21.15g %21.15g : uu=%21.15g %21.15g %21.15g pp=%21.15g %21.15g %21.15g\n",f[pl],fe[pl],fi[pl],uu[pl],uue[pl],uui[pl],pp[pl],ppe[pl],ppi[pl]);
2479  f[pl]=fe[pl];
2480  uuallabs[pl]=uuallabse[pl];
2481  Gdpl[pl]=Gdple[pl];
2482  Gallabs[pl]=Gallabse[pl];
2483 
2484  fnorm[pl]=fnorme[pl];
2485  freport[pl]=freporte[pl];
2486  uu[pl]=uue[pl];
2487  pp[pl]=ppe[pl];
2488  }
2489 
2490  Tgas=Tgase;
2491  Trad=Trade;
2492  chieff=chieffe;
2493 
2494  *errorabs=errorabse;
2495  *errorallabs=errorallabse;
2496  *convreturn=convreturne;
2497  *q=qe;
2498 
2499  FTYPE tautote,tautotmaxe;
2500  calc_tautot_chieff(ppe, chieffe, ptrgeom, q, &tautote, &tautotmaxe);
2501 
2502  tautot=tautote;
2503  tautotmax=tautotmaxe;
2504  *tautotmaxreturn=tautotmaxe;
2505 
2506  }
2507 #if(0)
2508  else if(fabs(errorallabsi)<fabs(*errorallabs)){
2509  // if(ptrgeom->i==8 && ptrgeom->j==10) dualfprintf(fail_file,"initialchosenasguess: %g over %g and %g\n",errorallabse,*errorallabs,errorallabsi);
2510  PLOOP(pliter,pl){
2511  //if(ptrgeom->i==8 && ptrgeom->j==10) dualfprintf(fail_file,"fr=%21.15g %21.15g %21.15g : uu=%21.15g %21.15g %21.15g pp=%21.15g %21.15g %21.15g\n",f[pl],fe[pl],fi[pl],uu[pl],uue[pl],uui[pl],pp[pl],ppe[pl],ppi[pl]);
2512  f[pl]=fi[pl];
2513  uuallabs[pl]=uuallabsi[pl];
2514  Gdpl[pl]=Gdpli[pl];
2515  Gallabs[pl]=Gallabsi[pl];
2516 
2517  fnorm[pl]=fnormi[pl];
2518  freport[pl]=freporti[pl];
2519  uu[pl]=uui[pl];
2520  pp[pl]=ppi[pl];
2521  }
2522 
2523  Tgas=Tgasi;
2524  Trad=Tradi;
2525  chieff=chieffi;
2526 
2527  *errorabs=errorabsi;
2528  *errorallabs=errorallabsi;
2529  *convreturn=convreturni;
2530  *q=qi;
2531 
2532  FTYPE tautoti,tautotmaxi;
2533  calc_tautot_chieff(ppi, chieffi, ptrgeom, q, &tautoti, &tautotmaxi);
2534 
2535  tautot=tautoti;
2536  tautotmax=tautotmaxi;
2537  *tautotmaxreturn=tautotmaxi;
2538 
2539  }
2540 #endif
2541  else{
2542  // if(ptrgeom->i==8 && ptrgeom->j==10) dualfprintf(fail_file,"originalguesserror: %g over %g\n",errorallabse,*errorallabs);
2543  }
2544  }
2545  }
2546 #endif
2547 
2548 
2549 
2550 
2551 
2552 
2553 
2554 
2555 
2556 
2557 
2558 
2560  //
2561  // See if can do "trivial" explicit corresponding to machine level version of G=0 (i.e. when changes to u would be not noticible even if G is non-zero)
2562  //
2563  // At this point, even if first iteration, know whether source term is what contributes to changes in uu.
2564  // If no absolute force to machine precision for each absolute uu, then implicit stepping can be avoided.
2565  // Even if inversions led to no consistent inversion (e.g. raditive inversion uses ceilings and so uu!=uu0 even for G=0), the below is correct.
2566  // This even accounts for case where entropy or energy suggest need implicit
2567  // This even accounts for when RAD quantities or MHD quantities differ on whether need explicit, since go over all pl always.
2568  //
2569  // NO: Apparently guess can lead to small G, but next iteration may not. But generally iterations can slowly grow G, so can't use any iter condition either.
2570  // Ok, if iter=1, then check both tau and G (not either, but both) and also ensure only rad inversion changes, no gas inversion changes/issues/failures.
2572  *goexplicit=0; // default
2573 #define ITERCHECKEXPLICITSAFE 1 // iteration by which assume G has settled and can test if can go explicit.
2574  if(1){
2575  if(whichcall==FIMPLICITCALLTYPEF1){//FIMPLICITCALLTYPEJAC)
2576  // if( (iter>ITERCHECKEXPLICITSAFE || iter==1 && tautotmax<NUMEPSILON ) && failreturn<=UTOPRIMGENWRAPPERRETURNFAILRAD){
2577  if( (iter>ITERCHECKEXPLICITSAFE || iter==1 && tautotmax<NUMEPSILON ) ){
2578  // iter>1 so at least have estimate of G even if not great.
2579  // At iter=1, U->p->G can give G=0, while dUrad=-dUgas can still lead to changes that upon next iteration lead to G!=0.
2580  *goexplicit=1;
2581  PLOOPDYNAMICAL(pliter,pl) if(fabs(Gallabs[pl])>NUMEPSILON*fabs(uuallabs[pl])) *goexplicit=0;
2582  pl=URAD0;
2583  if(fabs(ratchangeRtt*uu[pl])>NUMEPSILON*fabs(uuallabs[pl])) *goexplicit=0;
2584  if(fabs(ratchangeRtt*uu0[pl])>NUMEPSILON*fabs(uuallabs[pl])) *goexplicit=0;
2585  // if(*goexplicit) dualfprintf(fail_file,"Went explicit\n");
2586  // else dualfprintf(fail_file,"Stayed implicit\n");
2587  }
2588  }
2589  }
2590 
2591 
2592 
2593 
2594 
2595 
2596 #if(0)
2597  // compute difference vector between original and new 4-force's effect on conserved radiative quantities
2598  // NR1992 Eq. 16.6.16: y_{n+1} = y_n + h f(y_{n+1}) , so error function is f = (y_{n+1} - y_n) - h f(y_{n+1})
2599  // i.e. f->0 as change in conserved quantity approaches the updated value of 4-force
2600  if(0){
2601  if(fracenergy>0.0 && fracenergy<1.0){ // NOT USED!
2602  // then erefU=UU is set as default error term, so add entropy to this.
2603 
2604  FTYPE fentropy[NPR];
2605  FTYPE fnormentropy[NPR];
2606 
2607  // fracenergy=1.0;
2608  if(ru->startjac==TT){
2609  // Get final interpolated energy-entropy-term error function
2610  // dualfprintf(fail_file,"fracenergy=%g fUU=%g fnormUU=%g fE=%g fnormE=%g\n",fracenergy,f[UU],fnorm[UU],fentropy[ENTROPY],fnormentropy[ENTROPY]);
2611  f[UU] = fracenergy*fabs(f[UU]) + (1.0-fracenergy)*fabs(f[ENTROPY]);
2612  fnorm[UU] = fracenergy*fnorm[UU] + (1.0-fracenergy)*fnorm[ENTROPY];
2613  }
2614  }
2615  }
2616 #endif
2617 
2618 
2619 
2620 
2621 
2622 
2623 
2625  //
2626  // get alternative error
2627  //
2628  // Used in case optically thin and no interaction between RAD and GAS and radiation hits ceiling/floor and then must treat as ok since no force balance will help since no G and dUgas from dUrad will be wrong (and if u_g<<Erf, then would wrongly affect gas despite actually G<<U -- and if u_g>>Erf would no effect on gas be caused by that happening).
2629  //
2631 #if(ALLOWUSEUUALT) // purpose of this is equivalent to whether one can go explicit, but overly complicated and if reduces to using alternative when not desired, then not energy-momentum conserving
2632  if(whichcall==FIMPLICITCALLTYPEF1 && (iter==1 && tautotmax<NUMEPSILON) && failreturn<=UTOPRIMGENWRAPPERRETURNFAILRAD){//FIMPLICITCALLTYPEJAC
2633  // Have to check if really small error for alternative error, since otherwise f1iter loop won't work.
2634  // Only check on iter==1 since if moved beyond iter=1, then must be relevant 4-force. Only check if f1iter>1 because for f1iter=1 4-force is not set yet.
2635 
2636  // have to check if unmodified iterated quantities actually have smaller error, in which case probably U->P->Unew led to Unew different from U for iterated quantities due to no normal solution without fixups. When gas~rad in energy density, the other compnent can abosorb that error, but in limit that (say) RAD<<GAS, then dRAD won't register to GAS values and RAD will never converge if iterated on.
2637  FTYPE errorabsalt,errorallabsalt;
2638  FTYPE faltreport[NPR];
2639  int convreturnalt=f_error_check(showmessages, showmessagesheavy, iter, conv, convabs, realdt, dimtypef,*eomtype , *radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,pp,piin,falt,fnorm,faltreport,Uiin,uu0,uualt,ptrgeom,&errorabsalt,&errorallabsalt,whicherror,mtd,ru);
2640 
2641  // if(nstep>=32 && nstep<=46){
2642  // PLOOP(pliter,pl) dualfprintf(fail_file,"DEBUGIT: wc=%d iter=%d pl=%d uu0=%21.15g uu=%21.15g uualt=%21.15g Gdpl=%21.15g f=%21.15g falt=%21.15g errorabs=%21.15g errorabsalt=%21.15g radinvmod=%d radinvmodalt=%d failreturn=%d\n",whichcall,iter,pl,uu0[pl],uu[pl],uualt[pl],sign[pl]*localdt*Gdpl[pl],f[pl],falt[pl],*errorabs,errorabsalt,*radinvmod,radinvmodalt,failreturn);
2643  // }
2644 
2645 
2646 
2647  // see if alternative error is smaller *and* in converged limit. Catches cases when optically thin and ok that hits radiation ceiling.
2648  if(errorabsalt<*errorabs && convreturnalt==1){
2649  //dualfprintf(fail_file,"UsingALT\n");
2650 
2651  // then switch to use falt.
2652  // This typically controls what uu is used for the error
2653  // Eventually want uu to be consistent with pp
2654  // But allow for possible iteration upon uualt, so want to keep uu=uualt even though not consistent with pp
2655  // So have to fix uu(pp) once iterations are done.
2656  PLOOP(pliter,pl){
2657  uu[pl]=uualt[pl];
2658  pp[pl]=ppalt[pl];
2659  f[pl]=falt[pl];
2660  freport[pl]=faltreport[pl];
2661  }
2662  if(IMPUTYPE(mtd->implicititer)){
2663  // q based upon primitives, so if uu-method, then stuck with that q
2664  }
2665  else{
2666  // get new q(ppalt) now q(pp)
2667  get_state(pp, ptrgeom, q);
2668  // get new uu(ppalt) now uu(pp)
2669  primtoU(UNOTHING,pp,q,ptrgeom, uu, uuabs);
2670  }
2671  *convreturn=convreturnalt;
2672  *errorabs=errorabsalt;
2673  *errorallabs=errorallabsalt;
2674  *radinvmod=radinvmodalt;
2675  failreturn=failreturnalt;
2676  }
2677  }
2678 #endif
2679 
2680 
2681 
2682 
2683 
2684 
2685 
2686 #if(PRODUCTION==0)
2687  if(debugfail>=3){
2689  //
2690  // get stats on any Utoprimgen() newton calls
2691  //
2693  static long long int newtoncounttotal=0;
2694  newtoncounttotal+=newtonstats.lntries;
2695  static long long int newtoncounthere=0;
2696  newtoncounthere++;
2697  dualfprintf(fail_file,"Newtonstat: local=%d total=%d average=%21.15g\n",newtonstats.lntries,newtoncounttotal,(FTYPE)newtoncounttotal/(FTYPE)newtoncounthere);
2698  }
2699 #endif
2700 
2701 
2702 
2703  if(failreturn && failreturn>failreturnallowable){
2704  prod0dualfprintf(showmessages && debugfail>=2,fail_file,"Utoprimgen_wrapper() failed, must return out of f_implicit(): %d vs. %d\n",failreturn,failreturnallowable);
2705  return(failreturn);
2706  }
2707 
2708  return(0);
2709  // else{
2710  // // save better guess for later inversion (including this inversion above) from this inversion
2711  // PLOOP(pliter,pl) pp0[pl]=pp[pl];
2712  // }
2713 }
2714 
2715 
2716 
2717 
2719 static FTYPE compute_dt(int isexplicit, FTYPE *CUf, FTYPE *CUimp, FTYPE dtin)
2720 {
2721  // what's applied to source and flux terms to get update (see global.stepch.h and step_ch.c:get_truetime_fluxdt() and step_ch.c:setup_rktimestep()) to get Uf
2722  // We don't use the ucum update version of dt. As part of the RK method, the ucum update is separate from the substeps used to get information on updates(?). GODMARK.
2723 
2724  if(isexplicit==1 || isexplicit==0 && TIMETYPE==TIMEEXPLICIT){
2725  return(CUf[2]*dtin);
2726  }
2727  else{
2728  // if TIMETYPE==TIMEIMPLICIT and isexplicit==0, then use implicit dt
2729  // [0] because was fed single value at correct current stage.
2730  return(CUimp[0]*dtin);
2731  }
2732 }
2733 
2734 
2735 
2736 
2737 
2738 
2739 
2740 // KORALTODOMAYBE: average good neighbor if can. only use alternative backup if no good neighbor.
2741 
2742 
2744 static int koral_source_rad_implicit(int *eomtype, FTYPE *pb, FTYPE *pf, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE dissmeasure, FTYPE *dUother ,FTYPE (*dUcomp)[NPR])
2745 {
2746  int i=ptrgeom->i;
2747  int j=ptrgeom->j;
2748  int k=ptrgeom->k;
2749  int p=ptrgeom->p;
2750 
2751 
2752 
2753  // whether SPC
2754  int isspc=ISSPCMCOORD(MCOORD);
2755  // whether SPC with BH
2756  int isbhspc=ISSPCMCOORD(MCOORD) && ISBLACKHOLEMCOORD(MCOORD);
2757 
2759  //
2760  // get coordinate position of cell
2761  //
2763  int iiii=ptrgeom->i;
2764  int jjjj=ptrgeom->j;
2765  int kkkk=ptrgeom->k;
2766  int llloc=ptrgeom->p;
2767  FTYPE V[NDIM]={0.0};
2768  bl_coord_ijk(iiii,jjjj,kkkk,llloc,V);
2769 
2770 
2771  int modemethodlocal=MODEMETHOD;
2772  int reducetoquick=0;
2773 
2774  if(isspc){
2775  // tj=-2,-1,0,1 work
2776  // tj=ts2+1,ts2,ts2-1,ts2-2 work
2777  // revert to simple mode if POLEDEATH is active because then anyways solution near pole is inaccurate and whatever generated here would be overwritten.
2778  // doing this because with or without poledeath active, the poles often find no solution at all or at least not with the fast PMHD method, so the pole alone causes things to slow down alot for the whole code.
2779  int EXTRAPOLEDEATH=0,localpoledeath=0;
2780  FTYPE tj=(FTYPE)(startpos[2]+j);
2781 
2782  EXTRAPOLEDEATH=POLEDEATH;
2783  localpoledeath=POLEDEATH + EXTRAPOLEDEATH;
2784  if(fabs(tj+0.5 - (FTYPE)(0))<(FTYPE)localpoledeath || fabs(tj+0.5-(FTYPE)totalsize[2])<(FTYPE)localpoledeath){
2785  modemethodlocal=MODEPICKBESTSIMPLE;
2786  reducetoquick=2;
2787  // dualfprintf(fail_file,"j=%d modechange\n",j); // debug
2788  }
2789 
2790 
2791 
2792  EXTRAPOLEDEATH=1;
2793  localpoledeath=POLEDEATH + EXTRAPOLEDEATH;
2794  if(fabs(tj+0.5 - (FTYPE)(0))<(FTYPE)localpoledeath || fabs(tj+0.5-(FTYPE)totalsize[2])<(FTYPE)localpoledeath){
2795  modemethodlocal=MODEPICKBESTSIMPLE;
2796  reducetoquick=2;
2797  // dualfprintf(fail_file,"j=%d modechange\n",j); // debug
2798  }
2799 
2800  if(fabs(tj+0.5 - (FTYPE)(0))<(FTYPE)POLEDEATH || fabs(tj+0.5-(FTYPE)totalsize[2])<(FTYPE)POLEDEATH){
2801  modemethodlocal=MODEPICKBESTSIMPLE;
2802  if(LIMITEDPOLEDEATHINRADIUS && isbhspc){
2803  FTYPE Rhorref=rhor_calc(0);
2804 
2805  if( (1||V[1]>0.9*Rhorref) && (V[1]<OUTERDEATHRADIUS && OUTERDEATH==1 || OUTERDEATH==0)) reducetoquick=2;
2806  else reducetoquick=1;
2807  }
2808  else reducetoquick=1;
2809  }
2810  }// end if isspc
2811 
2812 
2813 
2814 
2815 
2816 
2817 
2818 
2819 
2820  int pliter,pl;
2821  int sc;
2822 
2823  int failreturn,noprims;
2824  int havebackup,didentropyalready;
2825  int usedenergy=0,usedentropy=0,usedboth=0,usedcold=0,usedimplicit=0,usedexplicitgood=0,usedexplicitkindabad=0,usedexplicitbad=0;
2826  int methodindex[NUMPRIORITERMETHODINDEX]={0};
2827  int ooo;
2828  for(ooo=0;ooo<NUMPRIORITERMETHODINDEX;ooo++){
2829  methodindex[ooo]=PRIORITERMETHODNOTSET;
2830  }
2831 
2832  // set backups that might change and contaminate a fresh start
2833  // piin, Uiin, Ufin, CUf, CUimp, ptrgeom, dUother don't change, rest can.
2834  int failfinalreturn;
2835  int eomtypelocal;
2836 
2837 
2838 
2840  //
2841  // Setup pb and uub that hold final primitive and conserved solutions
2842  //
2844 
2846  // set full uu0
2847  FTYPE fracdtuu0=1.0;
2848  FTYPE uu0[NPR],dUtot[NPR],rdUtot[NPR];
2849  FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
2850  PLOOP(pliter,pl){
2851  uu0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall); // initial+flux value of U. Only feed in full CUf, not CUimp
2852  dUtot[pl] = uu0[pl]-Uiin[pl]; // absolute change due to flux-advection step
2853  rdUtot[pl] = fabs(uu0[pl]-Uiin[pl])/(fabs(uu0[pl])+fabs(Uiin[pl])); // relative change to energy due to flux-advection step
2854  }
2855 
2856  // but we end up modifying pb, not pf.
2857  FTYPE uub[NPR]; // holds returned uu from implicit solver
2858  // for implicit scheme, set pf->pb in case pf contains final time information like the magnetic field
2859  // at this point, pb=pf was used to compute Flux(pb=pf), while uu0 is result of that flux. Best for optically thin regime, but better guess limits used in actual solver.
2860  PLOOP(pliter,pl){
2861  pb[pl] = pf[pl]; // piin[pl];
2862  uub[pl] = uu0[pl]; //Uiin[pl]; // at this point, best approximation can make, but do better in solver itself
2863  }
2864 
2865 
2866 
2868  //
2869  // setup backup's for reversions of starting guess or solution
2870  //
2872  FTYPE pbbackup[NPR];
2873  FTYPE uubbackup[NPR];
2874  FTYPE dUcompbackup[NUMSOURCES][NPR];
2875  struct of_state qbackup;
2876  PLOOP(pliter,pl){
2877  pbbackup[pl]=pb[pl]; // at this point, best approximation can make, but do better in solver itself
2878  uubbackup[pl]=uub[pl]; // at this point, best approximation can make, but do better in solver itself
2879  SCLOOP(sc) dUcompbackup[sc][pl]=dUcomp[sc][pl]; // stores dUcomp so far computed from other physical terms
2880  }
2881  qbackup=*q; // at this point, best approximation can make, but do better in solver itself
2882 
2883 
2885  //
2886  // It's up to inversion method to set failure flags, not utoprimgen() that just checks them mostly (it might modify them based upon doing reductions).
2887  // setup pflags
2888  //
2890  PFTYPE *lpflag,*lpflagrad;
2891  lpflag=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMFAIL);
2892  lpflagrad=&GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL);
2893  // set default
2894  *lpflag=UTOPRIMNOFAIL;
2895  *lpflagrad=UTOPRIMRADNOFAIL;
2896 
2897 
2899  //
2900  // default is didn't get good primitives. Similar, but slightly different from, failreturn
2901  //
2903  failreturn=1;
2904  noprims=1;
2905  usedenergy=0;
2906  usedentropy=0;
2907  usedboth=0;
2908  usedcold=0;
2909  usedimplicit=0;
2910 
2911 
2912  // whether doing energy at all
2913  int eomtypecond[NUMEOMTYPES];
2914  eomtypecond[EOMFFDE]=(*eomtype==EOMFFDE || *eomtype==EOMDEFAULT && EOMTYPE==EOMFFDE);
2915  eomtypecond[EOMFFDE2]=(*eomtype==EOMFFDE2 || *eomtype==EOMDEFAULT && EOMTYPE==EOMFFDE2);
2916  eomtypecond[EOMCOLDGRMHD]=(*eomtype==EOMCOLDGRMHD || *eomtype==EOMDEFAULT && EOMTYPE==EOMCOLDGRMHD);
2917  eomtypecond[EOMENTROPYGRMHD]=(*eomtype==EOMENTROPYGRMHD || *eomtype==EOMDEFAULT && EOMTYPE==EOMENTROPYGRMHD);
2918  eomtypecond[EOMGRMHD]=(*eomtype==EOMGRMHD || *eomtype==EOMDEFAULT && EOMTYPE==EOMGRMHD);
2919  int testeom,counteom=0;
2920  for(testeom=0;testeom<NUMEOMTYPES;testeom++) if(eomtypecond[testeom]) counteom++;
2921  if(counteom>1){
2922  dualfprintf(fail_file,"Too many default eomtypeconds\n");
2923  for(testeom=0;testeom<NUMEOMTYPES;testeom++) dualfprintf(fail_file,"%d %d\n",testeom,eomtypecond[testeom]);
2924  myexit(843968364);
2925  }
2926 
2927 
2929  //
2930  // diags
2931  //
2933  FTYPE errorabs[NUMERRORTYPES]={1}; // 0: over iterated pl and 1: over full relavant pl
2934  int iters=0;
2935  int f1iters=0;
2936  int nummhdinvs=0;
2937  int nummhdsteps=0;
2938  FTYPE fracenergy;
2939  int itermode;
2940  int baseitermethod;
2941  int radinvmod=0;
2942  int whichcap;
2943  FTYPE trueimptryconv=IMPTRYCONV;
2944  FTYPE trueimpokconv=IMPOKCONV;
2945  FTYPE trueimpallowconv=IMPALLOWCONVCONST;
2946  int trueimpmaxiter=IMPMAXITERLONG;
2947  int truenumdampattempts=NUMDAMPATTEMPTS;
2948  int goexplicit;
2949 
2950 
2951 
2952 
2953 
2954 
2956  //
2957  // MODEENERGY
2958  //
2960 
2961  if(modemethodlocal==MODEENERGY && eomtypecond[EOMGRMHD]==1 || modemethodlocal==MODEDEFAULT && *eomtype==EOMGRMHD){
2962  havebackup=0;
2963  didentropyalready=0;
2964  eomtypelocal=*eomtype;
2965  errorabs[0]=errorabs[1]=1.0;
2966  fracenergy=1.0;
2967  itermode=ITERMODESTAGES;
2968  baseitermethod=QTYPMHD;
2969  //itermode=ITERMODENORMAL;
2970  // baseitermethod=QTYURAD;
2971 
2972  // NOTES: ITERMODESTAGES with QTYPMHD always goes to damp and sometimes fails with RADTUBE. Lots of Jsub issues, etc. Probably not right. Compared to ramesh code, settles on different u -- far too large even though error in f1[0] small.
2973  // Actually, if don't switch to PRAD, goes kinda ok with only 2 early failures, but needs to damp every time. Can't be right. So 2 issues. Very broad iteration tail.
2974 
2975  // but, ITERMODESTAGES with QTYURAD does fine, even if takes more iterations.
2976  // but, ITERMODESTAGES with QTYPRAD does kinda ok, 6 early bads and ~20 damps, but then settles.
2977 
2978  whichcap=CAPTYPEBASIC;
2979  failreturn=koral_source_rad_implicit_mode(modemethodlocal,1,0,havebackup, didentropyalready, &eomtypelocal, whichcap, itermode, &baseitermethod, trueimptryconv, trueimpokconv, trueimpallowconv, trueimpmaxiter, truenumdampattempts, fracenergy, dissmeasure, &radinvmod, pb, uub, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, q, dUother ,dUcomp, errorabs, errorabs, &iters, &f1iters, &nummhdinvs, &nummhdsteps);
2980  if(ACTUALHARDFAILURE(failreturn)){
2981  failfinalreturn=1;
2982  *lpflag=UTOPRIMFAILCONV;
2983  *lpflagrad=UTOPRIMRADFAILCASE1A;
2984  // restore backups in case got contaminated
2985  PLOOP(pliter,pl){
2986  pb[pl]=pbbackup[pl];
2987  uub[pl]=uubbackup[pl];
2988  SCLOOP(sc) dUcomp[sc][pl]=dUcompbackup[sc][pl];
2989  }
2990  *q=qbackup;
2991  goexplicit=0;
2992  usedimplicit=1;
2993  }
2994  else if(failreturn>=0){
2995  failfinalreturn=0;
2996  noprims=0;
2997  *eomtype=eomtypelocal; // can be EOMDONOTHING if successful and small enough error
2998  usedenergy=1;
2999  goexplicit=0;
3000  usedimplicit=1;
3001  }
3002  else{
3003  failfinalreturn=FAILRETURNGOTRIVIALEXPLICIT; // indicates to koral_source_rad() that implicit says just do trivial explicit
3004  noprims=1;
3005  *eomtype=EOMGRMHD;
3006  goexplicit=1;
3007  usedexplicitgood=1;
3008  }
3009  }
3010 
3012  //
3013  // MODEENTROPY
3014  //
3016 
3017  if(modemethodlocal==MODEENTROPY || modemethodlocal==MODEDEFAULT && *eomtype==EOMENTROPYGRMHD){
3018  havebackup=0;
3019  didentropyalready=0;
3020  eomtypelocal=EOMENTROPYGRMHD;
3021  errorabs[0]=errorabs[1]=1.0;
3022  fracenergy=0.0;
3023  itermode=ITERMODESTAGES;
3024  whichcap=CAPTYPEBASIC;
3025  baseitermethod=QTYPMHD;
3026  failreturn=koral_source_rad_implicit_mode(modemethodlocal,1,0,havebackup, didentropyalready, &eomtypelocal, whichcap, itermode, &baseitermethod, trueimptryconv, trueimpokconv, trueimpallowconv, trueimpmaxiter, truenumdampattempts, fracenergy, dissmeasure, &radinvmod, pb, uub, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, q, dUother ,dUcomp, errorabs, errorabs, &iters, &f1iters, &nummhdinvs, &nummhdsteps);
3027  if(ACTUALHARDFAILURE(failreturn)){
3028  failfinalreturn=1;
3029  *lpflag=UTOPRIMFAILCONV;
3030  *lpflagrad=UTOPRIMRADFAILCASE1A;
3031  // restore backups in case got contaminated
3032  PLOOP(pliter,pl){
3033  pb[pl]=pbbackup[pl];
3034  uub[pl]=uubbackup[pl];
3035  SCLOOP(sc) dUcomp[sc][pl]=dUcompbackup[sc][pl];
3036  }
3037  *q=qbackup;
3038  goexplicit=0;
3039  usedimplicit=1;
3040  }
3041  else if(failreturn>=0){
3042  failfinalreturn=0;
3043  noprims=0;
3044  *eomtype=eomtypelocal; // can be EOMDONOTHING if successful and small enough error
3045  usedentropy=1;
3046  goexplicit=0;
3047  usedimplicit=1;
3048  }
3049  else{
3050  failfinalreturn=FAILRETURNGOTRIVIALEXPLICIT; // indicates to koral_source_rad() that implicit says just do trivial explicit
3051  noprims=1;
3052  *eomtype=EOMENTROPYGRMHD;
3053  goexplicit=1;
3054  usedexplicitgood=1;
3055  }
3056  }
3057 
3058 
3059 
3060 
3061 
3062  if(modemethodlocal==MODEENERGYRAMESH&&USERAMESH){
3063  // these ramesh solutions are here so both entropy and energy can have chance to fill them.
3064  int gotrameshsolution=0;
3065  FTYPE ppeng[NPR]={0},ppent[NPR]={0},errorabseng[NUMERRORTYPES],errorabsent[NUMERRORTYPES];
3066  set_array(errorabseng,NUMERRORTYPES,MPI_FTYPE,1.0);
3067  set_array(errorabsent,NUMERRORTYPES,MPI_FTYPE,1.0);
3068  int failtypeeng=1,failtypeent=1,iterseng=IMPMAXITERLONG,itersent=IMPMAXITERLONG,radinvmodeng=-1,radinvmodent=-1;
3069  struct of_state qeng, qent;
3070  FTYPE uueng[NPR]={0.0},uuent[NPR]={0.0};
3071  qeng=qbackup;
3072  qent=qbackup;
3073  FTYPE dUcompeng[NUMSOURCES][NPR],dUcompent[NUMSOURCES][NPR];
3074 
3075 
3076  goexplicit=0; // force since no explicit check
3077  FTYPE errorabsforramesh[NUMERRORTYPES];
3078  set_array(errorabsforramesh,NUMERRORTYPES,MPI_FTYPE,1.0);
3079 
3080  PLOOP(pliter,pl){
3081  pb[pl]=pbbackup[pl];
3082  uub[pl]=uubbackup[pl];
3083  SCLOOP(sc) dUcompeng[sc][pl]=dUcomp[sc][pl]=dUcompbackup[sc][pl];
3084  }
3085  *q=qbackup;
3086  //
3087  // BEGIN GET RAMESH SOLUTION
3088  failreturn=FAILRETURNGENERAL;// default to fail
3089  *eomtype=EOMGRMHD;
3090  int whichcall=*eomtype;
3091  get_rameshsolution_wrapper(whichcall, *eomtype, errorabsforramesh, ptrgeom, pb, piin, Uiin, Ufin, dUother, CUf, CUimp, q, ppeng, ppent, uueng, uuent, dUcompeng, dUcompent, &qeng, &qent, &failtypeeng, errorabseng, &iterseng, &radinvmodeng, &failtypeent, errorabsent, &itersent, &radinvmodent);
3092  gotrameshsolution=1; // indicates did at least attempt ramesh soltion call
3093  // translate
3094  PLOOP(pliter,pl){
3095  pb[pl]=ppeng[pl];
3096  uub[pl]=uueng[pl];
3097  SCLOOP(sc) dUcomp[sc][pl]=dUcompeng[sc][pl];
3098  }
3099  *q=qeng;
3100  //
3101  *lpflag=*lpflagrad=(PFTYPE)failtypeeng; // need better translation
3102  radinvmod=radinvmodeng;
3103  // radErfneg=0; // not allowed, considered BADNEG type
3104  iters=iterseng;
3105  errorabs[0]=errorabseng[0];
3106  errorabs[1]=errorabseng[1];
3107  if(failtypeeng || errorabs[WHICHERROR]>IMPALLOWCONVCONSTABS){
3108  failfinalreturn=1;
3109  failreturn=FAILRETURNGENERAL; *eomtype=EOMGRMHD;
3110  // restore backups in case got contaminated
3111  PLOOP(pliter,pl){
3112  pb[pl]=pbbackup[pl];
3113  uub[pl]=uubbackup[pl];
3114  SCLOOP(sc) dUcomp[sc][pl]=dUcompbackup[sc][pl];
3115  }
3116  *q=qbackup;
3117  goexplicit=0;
3118  usedimplicit=1;
3119  }
3120  else if(errorabs[WHICHERROR]<IMPTRYCONVABS){
3121  failfinalreturn=0;
3122  failreturn=FAILRETURNNOFAIL;
3123  noprims=0;
3124  *eomtype=EOMDIDGRMHD;
3125  usedenergy=1;
3126  goexplicit=0;
3127  usedimplicit=1;
3128  }
3129  else{
3130  failreturn=FAILRETURNNOTTOLERROR; *eomtype=EOMDIDGRMHD;
3131  failfinalreturn=1;
3132  noprims=1;
3133  *eomtype=EOMGRMHD;
3134  usedenergy=1;
3135  goexplicit=0;
3136  usedimplicit=1;
3137  }
3138  // END GET RAMESH SOLUTION
3139  }
3140 
3141 
3142 
3143 
3145  //
3146  // MODESWITCH
3147  //
3149 
3150  if(modemethodlocal==MODESWITCH && eomtypecond[EOMGRMHD]==1){
3151  FTYPE errorabsenergy[NUMERRORTYPES],errorabsentropy[NUMERRORTYPES];
3152  set_array(errorabsenergy,NUMERRORTYPES,MPI_FTYPE,1.0);
3153  set_array(errorabsentropy,NUMERRORTYPES,MPI_FTYPE,1.0);
3154 
3155  int itersenergy=0,itersentropy=0;
3156  int f1itersenergy=0,f1itersentropy=0;
3157  int nummhdinvsenergy=0,nummhdinvsentropy=0;
3158  int nummhdstepsenergy=0,nummhdstepsentropy=0;
3159  int itermodeenergy,itermodeentropy;
3160  int baseitermethodenergy,baseitermethodentropy;
3161  int whichcapenergy,whichcapentropy;
3162  FTYPE trueimptryconvenergy,trueimptryconventropy;
3163  FTYPE trueimpokconvenergy,trueimpokconventropy;
3164  FTYPE trueimpallowconvenergy,trueimpallowconventropy;
3165  int trueimpmaxiterenergy,trueimpmaxiterentropy;
3166  int truenumdampattemptsenergy,truenumdampattemptsentropy;
3167  int failreturnenergy=FAILRETURNGENERAL; // default
3168  int failreturnentropy=FAILRETURNGENERAL; // default
3169 
3170  eomtypelocal=*eomtype;
3171  havebackup=1; // only time this is used is here where we tell energy that we have backup method, so can give up quickly.
3172  didentropyalready=0;
3173  fracenergy=1.0;
3174  errorabsenergy[0]=errorabsenergy[1]=1.0;
3175  itermodeenergy=ITERMODESTAGES;
3176  whichcapenergy=CAPTYPEBASIC;
3177  trueimptryconvenergy=IMPTRYCONV;
3178  trueimpokconvenergy=IMPOKCONVCONST;
3179  trueimpallowconvenergy=IMPALLOWCONVCONST;
3180  trueimpmaxiterenergy=IMPMAXITERLONG;
3181  truenumdampattemptsenergy=NUMDAMPATTEMPTS;
3182  baseitermethodenergy=QTYPMHD;
3183  failreturnenergy=koral_source_rad_implicit_mode(modemethodlocal,1,0,havebackup, didentropyalready, &eomtypelocal, whichcapenergy, itermodeenergy, &baseitermethodenergy, trueimptryconvenergy, trueimpokconvenergy, trueimpallowconvenergy, trueimpmaxiterenergy, truenumdampattemptsenergy, fracenergy, dissmeasure, &radinvmod, pb, uub, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, q, dUother ,dUcomp, errorabsenergy, errorabsenergy, &itersenergy, &f1itersenergy, &nummhdinvsenergy, &nummhdstepsenergy);
3184  nummhdsteps+=nummhdstepsenergy;
3185 
3186  if(SWITCHGOODIDEAFAILURE(failreturn) && eomtypecond[EOMGRMHD]){
3187  // if failed with GRMHD or return reported switching to entropy is preferred, then do entropy method
3188  eomtypelocal=EOMENTROPYGRMHD;
3189  // restore backups for fresh start
3190  PLOOP(pliter,pl){
3191  pb[pl]=pbbackup[pl];
3192  uub[pl]=uubbackup[pl];
3193  SCLOOP(sc) dUcomp[sc][pl]=dUcompbackup[sc][pl];
3194  }
3195  *q=qbackup;
3196  // get fresh start entropy solution
3197  havebackup=0;
3198  didentropyalready=0;
3199  fracenergy=0.0;
3200  errorabsentropy[0]=errorabsentropy[1]=1.0;
3201  itermodeentropy=ITERMODESTAGES;
3202  whichcapentropy=CAPTYPEBASIC;
3203  trueimptryconventropy=IMPTRYCONV;
3204  trueimpokconventropy=IMPOKCONVCONST;
3205  trueimpallowconventropy=IMPALLOWCONVCONST;
3206  trueimpmaxiterentropy=IMPMAXITERLONG;
3207  truenumdampattemptsentropy=NUMDAMPATTEMPTS;
3208  baseitermethodentropy=QTYPMHD;
3209  failreturnentropy=koral_source_rad_implicit_mode(modemethodlocal,1,0,havebackup, didentropyalready, &eomtypelocal, whichcapentropy, itermodeentropy, &baseitermethodentropy, trueimptryconventropy, trueimpokconventropy, trueimpallowconventropy, trueimpmaxiterentropy, truenumdampattemptsentropy, fracenergy, dissmeasure, &radinvmod, pb, uub, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, q, dUother ,dUcomp, errorabsentropy, errorabsentropy, &itersentropy, &f1itersentropy, &nummhdinvsentropy, &nummhdstepsentropy);
3210  nummhdsteps+=nummhdstepsentropy;
3211 
3212  if(ACTUALHARDFAILURE(failreturnentropy)){
3213  failfinalreturn=1;
3214  *lpflag=UTOPRIMFAILCONV;
3215  *lpflagrad=UTOPRIMRADFAILCASE1A;
3216  goexplicit=0;
3217  usedimplicit=1;
3218  if(debugfail>=2) dualfprintf(fail_file,"Entropy also failed: energy=%d entropy=%d\n",failreturnenergy,failreturnentropy);
3219  }
3220  else if(failreturnentropy>=0){
3221  // use entropy
3222  failfinalreturn=0;
3223  usedentropy=1;
3224  noprims=0;
3225  errorabs[0]=errorabsentropy[0];
3226  errorabs[1]=errorabsentropy[1];
3227  iters=itersentropy;
3228  f1iters=f1itersentropy;
3229  // tell an externals to switch to entropy
3230  //*eomtype=EOMENTROPYGRMHD;
3231  *eomtype=eomtypelocal; // EOMDONOTHING if successful call to koral_source_rad_implicit_mode()
3232  goexplicit=0;
3233  usedimplicit=1;
3234  }
3235  else{
3236  failfinalreturn=FAILRETURNGOTRIVIALEXPLICIT; // indicates to koral_source_rad() that implicit says just do trivial explicit
3237  noprims=1;
3238  *eomtype=EOMDEFAULT;
3239  iters=itersentropy;
3240  f1iters=f1itersentropy;
3241  goexplicit=1;
3242  usedexplicitgood=1;
3243  }
3244  }
3245  else if(failreturnenergy>=0){// failreturnenergy==0 or eomtypecond[EOMGRMHD]==0
3246  // can stick with energy
3247  failfinalreturn=0;
3248  usedenergy=1;
3249  noprims=0;
3250  errorabs[0]=errorabsenergy[0];
3251  errorabs[1]=errorabsenergy[1];
3252  iters=itersenergy;
3253  f1iters=f1itersenergy;
3254  // switch to whatever solver suggested if didn't meet go-entropy condition
3255  *eomtype=eomtypelocal; // can also be EOMDONOTHING if successful and good enough error.
3256  goexplicit=0;
3257  usedimplicit=1;
3258  if(ACTUALHARDFAILURE(failreturnenergy) && debugfail>=2) dualfprintf(fail_file,"Decided didn't meet go-entropy condition but failed: failreturn=%d eomtypelocal=%d\n",failreturn,eomtypelocal);
3259  }
3260  else{
3261  failfinalreturn=FAILRETURNGOTRIVIALEXPLICIT; // indicates to koral_source_rad() that implicit says just do trivial explicit
3262  noprims=1;
3263  *eomtype=EOMDEFAULT;
3264  iters=itersentropy;
3265  f1iters=f1itersentropy;
3266  goexplicit=1;
3267  usedexplicitgood=1;
3268  }
3269  }
3270 
3271 
3272 
3273 
3274 
3275 // KORALTODO: SUPERGODMARK: run normal koral tests. Figure out all entropy signs.
3276 // KORALTODO: SUPERGODMARK: Need backup to entropy since really dies if no backup. E.g. cold backup. But maybe using high accurate cold bad compared to lower accuracy entropy or lower accuracy energy. Not sure should always prefer entropy if didn't reach desired tolerance. But, currently if allowed tolerance, treated as ok solution and not failure to reject. So this issue is ok relative to chosen IMPALLOWCONV.
3277 
3278 
3279 
3280 
3281 
3282 
3283 
3285  //
3286  // MODEPICKBEST / MODEPICKBESTSIMPLE / MODEPICKBESTSIMPLE2
3287  //
3288  // KORALTODO: SUPERGODMARK: Need to still think of energy-entropy implicit solver for intermediate regime. Also, need to add conditions to avoid entropy or energy if Erf<0 or gammarad reaches limit or entropy-based effective absorption opacity is too large."
3289  //
3291  // 1) start with entropy
3292  // 2) Then if entropy didn't fail, use as guess for energy.
3293  // During energy iteration, stop if repeatedly have u_g[entropy]>2*u_g[energy] using entropy guess stored for reference.
3294  // 3) If energy failed, stick with non-failed entropy. If both failed, revert to failure modes or G=0
3295  // If both succeeded, use entropy if u_g[entropy]>2*u_g[energy]
3296 
3297  // NEW ORDER (because entropy dies too much in shocks and takes too many trials)
3298  // 1) Try energy with QTYPMHD, QTYURAD, QTYPRAD. Try quickly with no damping, ITERMODENORMAL. Only try URAD/PRAD if PMHD fails or gives radinv=1
3299  // 2) Following #1, but then use ITERMODESTAGES, damping, higher uu if applicable.
3300 
3301 #define NUMPHASES (6)
3302 #define NUMPHASESENT (8)
3303 #define NUMPHASESCOLD (1)
3304 
3305  // counters for which method was *attempted* even if not used
3306  static long long int tryphaselistenergy[NUMPHASES]={0};
3307  static long long int tryphaselistentropy[NUMPHASESENT]={0};
3308  static long long int tryphaselistcold[NUMPHASESCOLD]={0};
3309 
3310 
3311  int gotrameshsolution=0,usedrameshenergy=0,usedrameshentropy=0;
3312  if(modemethodlocal==MODEPICKBEST || modemethodlocal==MODEPICKBESTSIMPLE || modemethodlocal==MODEPICKBESTSIMPLE2){
3313 
3314 
3315 
3317  //
3318  // ENTROPY VARIABLES
3319  //
3321 
3322  // choices per attempt
3323  int itermodeentropy=ITERMODENORMAL; // start with normal
3324  int baseitermethodentropy=QTYPMHD; // default
3325  FTYPE trueimptryconventropy;
3326  FTYPE trueimpokconventropy;
3327  FTYPE trueimpallowconventropy;
3328  int trueimpmaxiterentropy;
3329  int truenumdampattemptsentropy;
3330  int whichcapentropy;
3331 
3332  // hold error and iterations from last attempt
3333  FTYPE errorabsentropyold[NUMERRORTYPES];
3334  set_array(errorabsentropyold,NUMERRORTYPES,MPI_FTYPE,1.0);
3335 
3336  int radinvmodentropyold=UTOPRIMRADFAILBAD1;
3337  int itersentropyold=0;
3338  // hold iterations for total entropy attempts
3339  int itersentropy=0;
3340  int f1itersentropy=0;
3341  int nummhdinvsentropy=0;
3342  int nummhdstepsentropy=0;
3343 
3344 
3345  // set that no entropy backup yet.
3346  havebackup=0;
3347  didentropyalready=0;
3348  fracenergy=0.0;
3349 
3350  // default in case no best solution with no error below 1.0 that is set as default best
3351 
3352  // holds best entropy solution
3353  FTYPE pbentropybest[NPR]; PLOOP(pliter,pl) pbentropybest[pl]=pbbackup[pl];
3354  FTYPE uubentropybest[NPR]; PLOOP(pliter,pl) uubentropybest[pl]=uubbackup[pl];
3355  FTYPE dUcompentropybest[NUMSOURCES][NPR]; PLOOP(pliter,pl) SCLOOP(sc) dUcompentropybest[sc][pl]=dUcompbackup[sc][pl];
3356  struct of_state qentropybest=qbackup;
3357  PFTYPE lpflagentropybest=1;
3358  PFTYPE lpflagradentropybest=1;
3359  int radinvmodentropybest=UTOPRIMRADFAILBAD1;
3360  int radErfnegentropybest=1;
3361  int failreturnentropybest=FAILRETURNGENERAL;
3362  int eomtypeentropybest=EOMENTROPYGRMHD;
3363  FTYPE errorabsentropybest[NUMERRORTYPES];
3364  set_array(errorabsentropybest,NUMERRORTYPES,MPI_FTYPE,1.0);
3365  int goexplicitentropybest=0;
3366 
3367  // holds latest entropy solution
3368  FTYPE pbentropy[NPR];
3369  FTYPE uubentropy[NPR]; // holds returned uu from implicit solver
3370  FTYPE dUcompentropy[NUMSOURCES][NPR]={{BIG}};
3371  struct of_state qentropy=qbackup;
3372  PFTYPE lpflagentropy=1;
3373  PFTYPE lpflagradentropy=1;
3374  int radinvmodentropy=UTOPRIMRADFAILBAD1;
3375  int radErfnegentropy=1;
3376  int failreturnentropy=FAILRETURNGENERAL; // default to fail in case energy not to be done at all
3377  int eomtypeentropy=EOMENTROPYGRMHD;
3378  FTYPE errorabsentropy[NUMERRORTYPES]; // default is high error
3379  set_array(errorabsentropy,NUMERRORTYPES,MPI_FTYPE,1.0);
3380  int goexplicitentropy=0;
3381 
3382 
3383 
3384 
3385 
3386 
3388  //
3389  // set fracenergy
3390  //
3392  set_fracenergy(ptrgeom->i,ptrgeom->j,ptrgeom->k,dissmeasure, &fracenergy);
3393 
3394 
3396  //
3397  // ENERGY VARIABLES
3398  //
3400 
3401  // hold old error and iterations
3402  FTYPE errorabsenergyold[NUMERRORTYPES];
3403  set_array(errorabsenergyold,NUMERRORTYPES,MPI_FTYPE,1.0);
3404  int radinvmodenergyold=UTOPRIMRADFAILBAD1;
3405  int itersenergyold;
3406 
3407  // latest energy iterations
3408  int itersenergy=0;
3409  int f1itersenergy=0;
3410  int nummhdinvsenergy=0;
3411  int nummhdstepsenergy=0;
3412 
3413  // setting for each attempt
3414  int itermodeenergy=ITERMODENORMAL; // start with normal
3415  int baseitermethodenergy=QTYPMHD; // default
3416  FTYPE trueimptryconvenergy;
3417  FTYPE trueimpokconvenergy;
3418  FTYPE trueimpallowconvenergy;
3419  int trueimpmaxiterenergy;
3420  int truenumdampattemptsenergy;
3421  int whichcapenergy;
3422 
3423 
3424  // holds best result from implicit solver
3425  FTYPE pbenergybest[NPR]; PLOOP(pliter,pl) pbenergybest[pl]=pbbackup[pl];
3426  FTYPE uubenergybest[NPR]; PLOOP(pliter,pl) uubenergybest[pl]=uubbackup[pl];
3427  FTYPE dUcompenergybest[NUMSOURCES][NPR]; PLOOP(pliter,pl) SCLOOP(sc) dUcompenergybest[sc][pl]=dUcompbackup[sc][pl];
3428  struct of_state qenergybest=qbackup;
3429  // default is best is fail situation
3430  PFTYPE lpflagenergybest=1;
3431  PFTYPE lpflagradenergybest=1;
3432  int radinvmodenergybest=UTOPRIMRADFAILBAD1;
3433  int radErfnegenergybest=1;
3434  int failreturnenergybest=FAILRETURNGENERAL;
3435  int eomtypeenergybest=EOMGRMHD;
3436  FTYPE errorabsenergybest[NUMERRORTYPES];
3437  set_array(errorabsenergybest,NUMERRORTYPES,MPI_FTYPE,1.0);
3438  int goexplicitenergybest=0;
3439 
3440  // holds result from implicit solver
3441  FTYPE pbenergy[NPR];
3442  FTYPE uubenergy[NPR];
3443  FTYPE dUcompenergy[NUMSOURCES][NPR];
3444  set_array(dUcompenergy,NUMSOURCES*NPR,MPI_FTYPE,BIG);
3445  struct of_state qenergy=qbackup;
3446  PFTYPE lpflagenergy=1;
3447  PFTYPE lpflagradenergy=1;
3448  int radinvmodenergy=UTOPRIMRADFAILBAD1;
3449  int radErfnegenergy=1;
3450  int failreturnenergy=FAILRETURNGENERAL; // default
3451  int eomtypeenergy=EOMGRMHD;
3452  FTYPE errorabsenergy[NUMERRORTYPES];
3453  set_array(errorabsenergy,NUMERRORTYPES,MPI_FTYPE,1.0);
3454  int goexplicitenergy=0;
3455 
3456 
3457 
3459  //
3460  // RAMESH VARIABLES AND DEFAULTS
3461  //
3462  // these ramesh solutions are here so both entropy and energy can have chance to fill them.
3463  //
3465  FTYPE ppeng[NPR],ppent[NPR];
3466  FTYPE uueng[NPR],uuent[NPR];
3467  FTYPE dUcompeng[NUMSOURCES][NPR],dUcompent[NUMSOURCES][NPR];
3468  PLOOP(pliter,pl){
3469  ppeng[pl]=ppent[pl]=pbbackup[pl];
3470  uueng[pl]=uuent[pl]=uubbackup[pl];
3471  SCLOOP(sc) dUcompeng[sc][pl]=dUcompent[sc][pl]=dUcompbackup[sc][pl];
3472  }
3473  struct of_state qeng=qbackup, qent=qbackup;
3474  FTYPE errorabseng[NUMERRORTYPES],errorabsent[NUMERRORTYPES];
3475  set_array(errorabseng,NUMERRORTYPES,MPI_FTYPE,1.0);
3476  set_array(errorabsent,NUMERRORTYPES,MPI_FTYPE,1.0);
3477  int failtypeeng=1,failtypeent=1,iterseng=IMPMAXITERLONG,itersent=IMPMAXITERLONG,radinvmodeng=UTOPRIMRADFAILBAD1,radinvmodent=UTOPRIMRADFAILBAD1;
3478 
3479 
3480 
3481 
3482 
3484  //
3485  // check if should re-order method attempt list in case where primary evolving quantity is radiation.
3486  //
3487  // assume at this stage that radiation primarily evolves if Erf sufficiently large compared to u_g or changes in URAD0 are sufficiently large
3488  //
3489  // check
3490  static FTYPE sqrtnumepsilon1;
3491  static FTYPE sqrtnumepsilon2;
3492  static int firsttimeset=1;
3493  if(firsttimeset){
3494  // sqrtnumepsilon=10.0*pow(NUMEPSILON,1.0/3.0);
3495  // sqrtnumepsilon=1E-1; // playing -- required for RADBONDI to be fast by using QTYURAD method first as QTYPMHD method fails more.
3496  sqrtnumepsilon1=MIN(1.0,10.0*NUMEPSILON/IMPTRYCONV);
3497  sqrtnumepsilon2=pow(NUMEPSILON,1.0/3.0);
3498  firsttimeset=0;
3499  }
3500  int radprimaryevolves=0;
3501  if(fabs(rdUtot[UU])<sqrtnumepsilon1*fabs(rdUtot[URAD0]) || fabs(uu0[URAD0])<sqrtnumepsilon1*fabs(uu0[UU]) || fabs(pb[URAD0])<sqrtnumepsilon1*fabs(pb[UU])){
3502  radprimaryevolves=1;
3503  }
3504  else{
3505  radprimaryevolves=0;
3506  }
3507  int radextremeprimaryevolves=0;
3508  if(fabs(rdUtot[UU])<10.0*NUMEPSILON*fabs(dUtot[URAD0]) || fabs(uu0[URAD0])<10.0*NUMEPSILON*fabs(uu0[UU]) || fabs(pb[URAD0])<10.0*NUMEPSILON*fabs(pb[UU])){
3509  radextremeprimaryevolves=1;
3510  }
3511  else{
3512  radextremeprimaryevolves=0;
3513  }
3514  int gasprimaryevolves=0;
3515  // if(radprimaryevolves==0 && (pb[URAD0]<sqrtnumepsilon2*pb[UU] || (-uu0[URAD0])<sqrtnumepsilon2*(-uu0[UU]))){
3516  // if(pb[URAD0]<sqrtnumepsilon2*pb[UU] || fabs(dUtot[URAD0])<sqrtnumepsilon2*fabs(dUtot[UU])){
3517  if(radprimaryevolves==0 && (fabs(rdUtot[URAD0])<sqrtnumepsilon2*fabs(rdUtot[UU]) || fabs(uu0[UU])<sqrtnumepsilon2*fabs(uu0[URAD0]) || fabs(pb[UU])<sqrtnumepsilon2*fabs(pb[URAD0]) )){
3518  gasprimaryevolves=1;
3519  }
3520  else{
3521  gasprimaryevolves=0;
3522  }
3523  int gasextremeprimaryevolves=0;
3524  if(radprimaryevolves==0 && radextremeprimaryevolves==0 && (fabs(rdUtot[URAD0])<10.0*NUMEPSILON*fabs(dUtot[UU]) || fabs(uu0[UU])<10.0*NUMEPSILON*fabs(uu0[URAD0]) || fabs(pb[UU])<10.0*NUMEPSILON*fabs(pb[URAD0]) )){
3525  gasextremeprimaryevolves=1;
3526  }
3527  else{
3528  gasextremeprimaryevolves=0;
3529  }
3530 
3531  if(LETPMHDFAIL){
3532  // just let pmhd fail or use total error in way that is setup now...
3533  // still allow extreme catches
3534  radprimaryevolves=0;
3535  gasprimaryevolves=0;
3536  }
3537 
3538  if(modemethodlocal==MODEPICKBESTSIMPLE){
3539  // forcing PMHD method, so must use gas
3540  radprimaryevolves=radextremeprimaryevolves=0;
3541  gasprimaryevolves=gasextremeprimaryevolves=1;
3542  }
3543 
3544 
3545  int bsqorhocond=0,funnelcond=0;
3546 #if(DOPERF)
3547  if(isspc){
3548  // HACK to force more use of PMHD method to avoid slowdown.
3549  if(q->bsq/pb[RHO]>1.0){
3550  bsqorhocond=1;
3551  }
3552  if(q->bsq/pb[RHO]>0.2*BSQORHOLIMIT || q->bsq/pb[UU]>0.2*BSQOULIMIT || pb[UU]/pb[RHO]>0.1*UORHOLIMIT){
3553  radprimaryevolves=radextremeprimaryevolves=0;
3554  gasprimaryevolves=gasextremeprimaryevolves=1;
3555  }
3556  if(q->bsq/pb[RHO]>0.2*BSQORHOLIMIT){
3557  funnelcond=1;
3558  }
3559  }
3560 #endif
3561 
3562 
3563 
3564 
3565  // DEBUG:
3566  // dualfprintf(fail_file,"PRIMARYEVOLVES: %d %d %d %d : pb=%g %g uu0=%g %g dUtot=%g %g : sqrtnumepsilon1=%g sqrtnumepsilon2=%g\n",radprimaryevolves,radextremeprimaryevolves,gasprimaryevolves,gasextremeprimaryevolves,pb[UU],pb[URAD0],-uu0[UU],-uu0[URAD0],dUtot[UU],dUtot[URAD0],sqrtnumepsilon1,sqrtnumepsilon2);
3567 
3568 
3569 
3571  //
3572  // store prior itermethod, before we change it.
3573  //
3575  int prioritermethodlist[NUMPRIORITERMETHODINDEX];
3576  int oo;
3577  for(oo=0;oo<NUMPRIORITERMETHODINDEX;oo++){
3578  prioritermethodlist[oo]=GLOBALMACP0A1(prioritermethod,i,j,k,oo);
3579  }
3580 
3581 
3582 
3584  //
3585  // GET ENERGY
3586  //
3587  // Now do energy if would use only energy or if doing interpolation
3588  // also check energy if entropy thinks we should do explicit
3589  //
3591  // if(prioritermethodlist[EOMINDEX] == EOMGRMHD || prioritermethodlist[EOMINDEX] == PRIORITERMETHODNOTSET && eomtypecond[EOMGRMHD] && (fracenergy!=0.0 || RADINVBAD(radinvmodentropy) || ACTUALHARDORSOFTFAILURE(failreturnentropy)==1 || goexplicitentropy==1)){
3592  if(eomtypecond[EOMGRMHD] && (fracenergy!=0.0 || RADINVBAD(radinvmodentropy) || ACTUALHARDORSOFTFAILURE(failreturnentropy)==1 || goexplicitentropy==1)){
3593 
3594 
3595  // quickly try QTYPMHD then QTYURAD
3596  int tryphase1;
3597 
3598  int baseitermethodlist[NUMPHASES]={QTYPMHD,QTYURAD,QTYPRAD,QTYPMHD,QTYURAD,QTYPRAD}; int whichfirstpmhd=0,whichfirsturad=1,whichfirstprad=2;
3600 #if(DOPERF)
3606 #else
3607  FTYPE trueimptryconvlist[NUMPHASES]={IMPTRYCONV,IMPTRYCONV,IMPTRYCONV,IMPTRYCONV,IMPTRYCONV,IMPTRYCONV};
3608  FTYPE trueimpokconvlist[NUMPHASES]={IMPTRYCONV,IMPTRYCONV,IMPTRYCONV,IMPTRYCONV,IMPTRYCONV,IMPTRYCONV};
3611  int truenumdampattemptslist[NUMPHASES]={NUMDAMPATTEMPTS,NUMDAMPATTEMPTS,NUMDAMPATTEMPTS,NUMDAMPATTEMPTS,NUMDAMPATTEMPTS,NUMDAMPATTEMPTS};
3612 #endif
3613  int modprimlist[NUMPHASES]={0,0,0,1,0,0};
3614  int checkradinvlist[NUMPHASES]={0,1,1,0,1,1};
3615  int eomtypelist[NUMPHASES]={EOMGRMHD,EOMGRMHD,EOMGRMHD,EOMGRMHD,EOMGRMHD,EOMGRMHD};
3616 
3617  // results in list
3618  FTYPE errorabslist[NUMPHASES][NUMERRORTYPES];
3619  set_array(errorabslist,NUMPHASES*NUMERRORTYPES,MPI_FTYPE,1.0);
3620  int radinvmodlist[NUMPHASES];
3621  set_array(radinvmodlist,NUMPHASES,MPI_INT,UTOPRIMRADFAILBAD1);
3622 
3623  // reorder method if desired
3624  // KORALNOTE: radinv check would nominally catch if PMHD method failed due to machine errors in GAS leading to huge changes in RAD leading to E_r<0 or gamma>gammaradmax, but might as well use desired method first.
3625  // normal checkradinvlist will catch if prad method doesn't lead to radinv but urad method does.
3626  // normal checkradinvlist will catch if somehow rad method leads to radinv but gas method doesn't.
3627  if(gasprimaryevolves==0){ // if gas primary evolves, then keep original order because PMHD is fastest method.
3628  if(radprimaryevolves){
3629  if(
3630  (USEPRIORITERMETHOD && (prioritermethodlist[BASEITERMETHODINDEX] == PRIORITERMETHODNOTSET || prioritermethodlist[BASEITERMETHODINDEX] == QTYURAD))
3631  || USEPRIORITERMETHOD==0
3632  ){
3633  tryphase1=-1;
3634  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0; whichfirsturad=tryphase1;
3635  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0; whichfirstprad=tryphase1;
3636  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=0; whichfirstpmhd=tryphase1;
3637  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0;
3638  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0;
3639  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=1;
3640  }
3641  if(
3642  USEPRIORITERMETHOD && prioritermethodlist[BASEITERMETHODINDEX] == QTYPRAD
3643  ){
3644  tryphase1=-1;
3645  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0; whichfirstprad=tryphase1;
3646  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0; whichfirsturad=tryphase1;
3647  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=0; whichfirstpmhd=tryphase1;
3648  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0;
3649  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0;
3650  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=1;
3651  }
3652  }// if rad is expected to need to be evolved
3653  }
3654 
3655 
3656 
3657 
3658 
3659 
3660  // ENERGY PHASE LOOP
3661  int firsttryphase1used=-1;
3662  for(tryphase1=0;tryphase1<NUMPHASES;tryphase1++){
3663 
3664  // dualfprintf(fail_file,"TRYING: tryphase1=%d : %d %d %d\n",tryphase1,gasextremeprimaryevolves,radextremeprimaryevolves,baseitermethodlist[tryphase1]);
3665 
3666  // pick best simple method avoids all solvers except PMHD
3667  if(modemethodlocal==MODEPICKBESTSIMPLE && baseitermethodlist[tryphase1]!=QTYPMHD) continue;
3668 
3669 #if(DOPERF)
3670  // pick best simple 2 method avoids all itermodestages methods
3671  if(modemethodlocal==MODEPICKBESTSIMPLE && itermodelist[tryphase1]==ITERMODESTAGES) continue;
3672  if(funnelcond){ // then don't expect to treat density accurate anyways, just need ok accuracy and stability
3673  trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONVMARGINAL);
3674  }
3675  // allow tolerance to be higher if...
3676  if(V[1]<Rhor && isbhspc){
3677  //trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONV_RHORHIGHERTOL);
3678  trueimpallowconvconstlist[tryphase1]=MAX(trueimpallowconvconstlist[tryphase1],IMPALLOWCONV_RHORHIGHERTOL);
3679  }
3680  else if(V[1]>OUTERDEATHRADIUS && OUTERDEATH==1){
3681  trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONV_ROUTERHIGHERTOL);
3682  }
3683 #else
3684  // pick best simple 2 method avoids all itermodestages methods
3685  if(modemethodlocal==MODEPICKBESTSIMPLE2 && itermodelist[tryphase1]==ITERMODESTAGES) continue;
3686 #endif
3687 
3688  // avoid method in case very non-dominant since then would give errorneous (critically bad even) results. If methods that can use fail, have to revert to entropy or fixups.
3689  if(radextremeprimaryevolves && baseitermethodlist[tryphase1]==QTYPMHD) continue;
3690  if(gasextremeprimaryevolves && (baseitermethodlist[tryphase1]==QTYURAD || baseitermethodlist[tryphase1]==QTYPRAD)) continue;
3691 
3692  if(radextremeprimaryevolves==0 && (baseitermethodlist[tryphase1]==QTYURAD || baseitermethodlist[tryphase1]==QTYPRAD) ){
3693  // if not in extreme radiative regime, then don't do damping for raditive schemes that are slow.
3694  truenumdampattemptslist[tryphase1]=NUMDAMPATTEMPTSQUICK;
3695  // and don't try to get too good of error.
3696  trueimptryconvlist[tryphase1]=IMPTRYCONVQUICK;
3697  // and avoid stages
3698  itermodelist[tryphase1]=ITERMODENORMAL;
3699  }
3700  if(gasextremeprimaryevolves==0 && (baseitermethodlist[tryphase1]==QTYPMHD)){
3701  // then still try to get good error since fast method, so no changes.
3702  }
3703 
3704 
3705  if(modemethodlocal==MODEPICKBESTSIMPLE){
3706  // do nothing, don't skip stages. Even when iteration-error is small, often stages can get both iteration and total errors to be small.
3707  }
3708  else{
3709  // If already tried QTYPMHD and that got error(0)<tol but error(1)>tol, then skip QTYPMHD with stages since should switch to QTYURAD or QTYPRAD because STAGES won't improve on error(1) if error(0)<tol.
3710  // independent of radinvmod. If ==0 or ==1, still should skip if error in that condition.
3711  if(baseitermethodlist[tryphase1]==QTYPMHD && errorabslist[whichfirstpmhd][0]<IMPTRYCONV && errorabslist[whichfirstpmhd][1]>IMPTRYCONV && WHICHERROR==1){
3712  // then should skip this case and rely upon radiative solvers
3713  continue;
3714  }
3715 
3716  if(baseitermethodlist[tryphase1]==QTYURAD && errorabslist[whichfirsturad][0]<IMPTRYCONV && errorabslist[whichfirsturad][1]>IMPTRYCONV && WHICHERROR==1){
3717  // then should skip this case and rely upon pmhd or prad
3718  continue;
3719  }
3720 
3721  if(baseitermethodlist[tryphase1]==QTYPRAD && errorabslist[whichfirstprad][0]<IMPTRYCONV && errorabslist[whichfirstprad][1]>IMPTRYCONV && WHICHERROR==1){
3722  // then should skip this case and rely upon pmhd or urad
3723  continue;
3724  }
3725 
3726  // if(prioritermethodlist[EOMTYPEINDEX]==EOMENTROPYGRMHD && itermodelist[tryphase1]==ITERMODESTAGES && errorabsenergybest[0]<IMPTRYCONV && errorabsenergybest[1]>IMPTRYCONV && WHICHERROR==1){
3727  // // then assume went through all ITERMODENORMAL cases and best error had good iteration tolerance, but best error has bad total error, and previous solution was entropy, so skip itermodestages.
3728  // // this assumes ITERMODESTAGES is expensive and should only do if ........
3729  // continue;
3730  // }
3731  }
3732 
3733 
3734  // dualfprintf(fail_file,"MAYBEREALLYTRYING: tryphase1=%d : %d %d %d\n",tryphase1,radinvmodenergybest,checkradinvlist[tryphase1],failreturnenergybest);
3735 
3736 
3737 
3738  // __WORKINGONIT__
3739  // if(baseitermethodlist[tryphase1]==QTYURAD || baseitermethodlist[tryphase1]==QTYPRAD) continue; // skip this method for now.
3740 
3741 
3742  if(reducetoquick){
3743  if(reducetoquick==1){
3744  trueimptryconvlist[tryphase1]=IMPTRYCONVSUPERQUICK;
3745  trueimpmaxiterlist[tryphase1]=1;
3746  }
3747  else{
3748  trueimptryconvlist[tryphase1]=IMPTRYCONVQUICK;
3749  trueimpmaxiterlist[tryphase1]=IMPMAXITERQUICK;
3750  }
3751  if(firsttryphase1used!=-1) continue;
3752  }
3753 
3754 
3755  // consider radinvmod only if error bad for original approach. Avoids excessive attempts when should hit radiative ceiling and error is small.
3756  // KORALTODO: KORALNOTE: If explicit was triggered (failreturnenergy) then could move on, but go ahead and test using other methods in case radinvmod!=0 can be avoided.
3757  //radinvmodenergybest!=0
3758 
3759  int needtotry;
3760  needtotry=(RADINVBAD(radinvmodenergybest) && checkradinvlist[tryphase1] || ACTUALHARDORSOFTFAILURE(failreturnenergybest) && failreturnenergybest!=FAILRETURNMODESWITCH);
3761 
3762  if(needtotry){
3763  if(firsttryphase1used==-1) firsttryphase1used=tryphase1;
3764  tryphaselistenergy[tryphase1]++;
3765 
3766  // dualfprintf(fail_file,"REALLYTRYING: tryphase1=%d\n",tryphase1);
3767 
3768 
3769  errorabsenergyold[0]=errorabsenergy[0];
3770  errorabsenergyold[1]=errorabsenergy[1];
3771  radinvmodenergyold=radinvmodenergy;
3772  itersenergyold=itersenergy;
3773  //
3774  whichcapenergy=CAPTYPEBASIC;
3775  //whichcapenergy=CAPTYPEBASIC;
3776  baseitermethodenergy=baseitermethodlist[tryphase1];
3777  itermodeenergy=itermodelist[tryphase1];
3778  trueimptryconvenergy=trueimptryconvlist[tryphase1];
3779  trueimpokconvenergy=(MAX(trueimptryconvlist[tryphase1],trueimpokconvlist[tryphase1]));
3780  trueimpallowconvenergy=(MAX(trueimptryconvlist[tryphase1],trueimpallowconvconstlist[tryphase1]));
3781  trueimpmaxiterenergy=trueimpmaxiterlist[tryphase1];
3782  truenumdampattemptsenergy=truenumdampattemptslist[tryphase1];
3783  int modprim=0;
3784  if(havebackup==0) modprim=modprimlist[tryphase1];
3785  //
3786  // start fresh
3787  *lpflag=UTOPRIMNOFAIL;
3788  *lpflagrad=UTOPRIMRADNOFAIL;
3789  radinvmodenergy=0;
3790  radErfnegenergy=0;
3791  failreturnenergy=FAILRETURNGENERAL; // default to fail in case energy not to be done at all
3792  eomtypeenergy=eomtypelist[tryphase1];
3793  errorabsenergy[0]=errorabsenergy[1]=1.0;
3794 
3795  // setup solver conditions for existence of backup solutions or entropy solution
3796  if(ACTUALHARDFAILURE(failreturnentropy)==1){
3797  havebackup=0; // no entropy solver solution, so no backup.
3798  didentropyalready=0;
3799  }
3800  else{
3801  havebackup=1; // here havebackup=1 means can break out of energy solver early if issues, since we do have entropy solver solution as backup.
3802  didentropyalready=1; // so can use entropy solution as reference for whether to stop energy iteration
3803  }
3804 
3805  // setup guess
3806  if(ACTUALHARDFAILURE(failreturnentropy)==1 || errorabsentropy[WHICHERROR]>ERRORTOUSEENTROPYFORENERGYGUESS){
3807  if(errorabsenergybest[WHICHERROR]>TRYHARDERFEEDGUESSTOL){
3808  PLOOP(pliter,pl){
3809  pbenergy[pl]=pbbackup[pl];
3810  uubenergy[pl]=uubbackup[pl];
3811  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompbackup[sc][pl];
3812  }
3813  qenergy=qbackup;
3814  errorabsenergy[0]=errorabsenergy[1]=1.0;
3815  radinvmodenergy=UTOPRIMRADFAILBAD1;
3816  }
3817  else{
3818  PLOOP(pliter,pl){
3819  pbenergy[pl]=pbenergybest[pl];
3820  uubenergy[pl]=uubenergybest[pl];
3821  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompbackup[sc][pl];
3822  }
3823  qenergy=qenergybest;
3824  errorabsenergy[0]=errorabsenergybest[0];
3825  errorabsenergy[1]=errorabsenergybest[1];
3826  radinvmodenergy=radinvmodenergybest;
3827  }
3828  }
3829  else{ // start with entropy
3830  PLOOP(pliter,pl){
3831  pbenergy[pl]=pbentropy[pl];
3832  uubenergy[pl]=uubentropy[pl];
3833  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompbackup[sc][pl];
3834  }
3835  qenergy=qentropy;
3836  errorabsenergy[0]=errorabsentropy[0]; // assume error estimate only used to decide if guess is used, not if converged with energy
3837  errorabsenergy[1]=errorabsentropy[1]; // assume error estimate only used to decide if guess is used, not if converged with energy
3838  radinvmodenergy=radinvmodentropy;
3839  }
3840  //
3841  failreturnenergy=koral_source_rad_implicit_mode(modemethodlocal,0,modprim,havebackup, didentropyalready, &eomtypeenergy, whichcapenergy, itermodeenergy, &baseitermethodenergy, trueimptryconvenergy, trueimpokconvenergy, trueimpallowconvenergy, trueimpmaxiterenergy, truenumdampattemptsenergy, fracenergy, dissmeasure, &radinvmodenergy, pbenergy, uubenergy, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, &qenergy, dUother ,dUcompenergy, errorabsenergy, errorabsenergybest, &itersenergy, &f1itersenergy, &nummhdinvsenergy, &nummhdstepsenergy);
3842  nummhdsteps+=nummhdstepsenergy;
3843 
3844  // store error, no matter if using solution or not or even if explicit
3845  errorabslist[tryphase1][0]=errorabsenergy[0];
3846  errorabslist[tryphase1][1]=errorabsenergy[1];
3847 
3848  if(failreturnenergy==FAILRETURNGOTRIVIALEXPLICIT){
3849  lpflagenergybest=*lpflag;
3850  lpflagradenergybest=*lpflagrad;
3851  radinvmodenergybest=radinvmodenergy;
3852  radErfnegenergybest=radErfnegenergy;
3853  failreturnenergybest=failreturnenergy;
3854  eomtypeenergybest=eomtypelist[tryphase1];
3855  goexplicitenergybest=1;
3856 
3857  // save which method ended up using
3858  int prioriter; for(prioriter=0;prioriter<NUMPRIORITERMETHODINDEX;prioriter++){
3859  methodindex[prioriter] = PRIORITERMETHODNOTSET; // back to unknown
3860  }
3861  }
3862  else{
3863  // see if want to keep
3864  // if(errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && ACTUALHARDFAILURE(failreturnenergy)==0 || failreturnenergy==FAILRETURNMODESWITCH){
3865  // if((errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && (RADINVBAD(radinvmodenergy)==0 || RADINVBAD(radinvmodenergybest) && RADINVBAD(radinvmodenergy)) || RADINVBAD(radinvmodenergybest) && RADINVBAD(radinvmodenergy)==0 && (errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR]||errorabsenergy[WHICHERROR]<IMPOKCONVABS)) && ACTUALHARDFAILURE(failreturnenergy)==0 || failreturnenergy==FAILRETURNMODESWITCH){
3866  if(
3867  (
3868  // best and no radinv problem
3869  errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && RADINVBAD(radinvmodenergy)==0
3870  // best because prior best also had radinv problem and still smaller error
3871  || errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && (RADINVBAD(radinvmodenergy) && RADINVBAD(radinvmodenergybest))
3872  // best because even though has radinv problem (while best doesn't) much smaller error
3873  || errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && errorabsenergy[WHICHERROR]<IMPOKCONVABS && errorabsenergybest[WHICHERROR]>100.0*IMPOKCONVABS && (RADINVBAD(radinvmodenergy) && RADINVBAD(radinvmodenergybest)==0)
3874  )
3875  && ACTUALHARDFAILURE(failreturnenergy)==0){
3876  // store result in case better than latter results
3877  lpflagenergybest=*lpflag;
3878  lpflagradenergybest=*lpflagrad;
3879  radinvmodenergybest=radinvmodenergy;
3880  radErfnegenergybest=radErfnegenergy;
3881  failreturnenergybest=failreturnenergy;
3882  eomtypeenergybest=eomtypeenergy;
3883  goexplicitenergybest=0;
3884  errorabsenergybest[0]=errorabsenergy[0];
3885  errorabsenergybest[1]=errorabsenergy[1];
3886  PLOOP(pliter,pl){
3887  pbenergybest[pl]=pbenergy[pl];
3888  uubenergybest[pl]=uubenergy[pl];
3889  SCLOOP(sc) dUcompenergybest[sc][pl]=dUcompenergy[sc][pl];
3890  }
3891  qenergybest=qenergy;
3892 
3893  // save which method ended up using
3894  methodindex[BASEITERMETHODINDEX] = baseitermethodlist[tryphase1];
3895  methodindex[ITERMODEINDEX] = itermodelist[tryphase1];
3896  methodindex[IMPTRYCONVINDEX] = (trueimptryconvlist[tryphase1]==IMPTRYCONV);
3897  methodindex[IMPMAXITERINDEX] = trueimpmaxiterlist[tryphase1];
3898  methodindex[NUMDAMPINDEX] = truenumdampattemptslist[tryphase1];
3899  methodindex[MODPRIMINDEX] = modprimlist[tryphase1];
3900  methodindex[CHECKRADINVINDEX] = checkradinvlist[tryphase1];
3901  methodindex[EOMTYPEINDEX] = eomtypelist[tryphase1];
3902  }
3903  }
3904 
3905  // still cost more iters
3906  itersenergy+=itersenergyold;
3907 
3908  int noproblem=(ACTUALHARDORSOFTFAILURE(failreturnenergy)==0 || failreturnenergy==FAILRETURNMODESWITCH);
3909 
3910 
3911  if(tryphase1!=firsttryphase1used && noproblem){
3912  if(debugfail>=2) dualfprintf(fail_file,"Recovered using tryphase1=%d (energy: failreturnenergy=%d radinvmod=%d -> %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g (best=%21.15g) iters: %d->%d baseitermethod=%d eomtype=%d\n",tryphase1,failreturnenergy,radinvmodenergyold,radinvmodenergy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsenergyold[WHICHERROR],errorabsenergy[WHICHERROR],errorabsenergybest[WHICHERROR],itersenergyold,itersenergy,baseitermethodenergy,eomtypeenergy);
3913  }
3914  if(noproblem==0){
3915  if(debugfail>=2) dualfprintf(fail_file,"Failed to: <Recovered> using tryphase1=%d (energy: failreturnenergy=%d radinvmod=%d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g (best=%21.15g) iters: %d->%d baseitermethod=%d eomtype=%d\n",tryphase1,failreturnenergy,radinvmodenergy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsenergyold[WHICHERROR],errorabsenergy[WHICHERROR],errorabsenergybest[WHICHERROR],itersenergyold,itersenergy,baseitermethodenergy,eomtypeenergy);
3916  }
3917 
3918 
3919  }// end if doing _mode() call
3920 
3921 
3922  }// end over try loop
3923 
3924 
3925 
3926 
3927 
3928 
3929 
3930 
3931  // see if want to try harder
3932  if(
3933  !(modemethodlocal==MODEPICKBESTSIMPLE2) // Ramesh method is like stages, so avoid if simple2 method
3934  && (ACTUALHARDORSOFTFAILURE(failreturnenergy) && failreturn!=FAILRETURNMODESWITCH && USERAMESH && radextremeprimaryevolves==0)
3935  && !(errorabslist[whichfirstpmhd][0]<IMPTRYCONV && errorabslist[whichfirstpmhd][1]>IMPTRYCONV) // avoid ramesh (pmhd-type) method if already did it and got iterate-small error.
3936  ){
3937  errorabsenergyold[0]=errorabsenergy[0];
3938  errorabsenergyold[1]=errorabsenergy[1];
3939  radinvmodenergyold=radinvmodenergy;
3940  itersenergyold=itersenergy;
3941  goexplicitenergy=0; // force since no explicit check
3942  //
3943  if(gotrameshsolution){// then just recall solution
3944  PLOOP(pliter,pl){
3945  pbenergy[pl]=ppeng[pl];
3946  uubenergy[pl]=uueng[pl];
3947  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompeng[sc][pl];
3948  }
3949  qenergy=qeng;
3950  //
3951  *lpflag=*lpflagrad=(PFTYPE)failtypeeng; // need better translation
3952  radinvmodenergy=radinvmodeng;
3953  radErfnegenergy=0; // not allowed, considered BADNEG type
3954  itersenergy=iterseng;
3955  errorabsenergy[0]=errorabseng[0];
3956  errorabsenergy[1]=errorabseng[1];
3957  if(failtypeeng || errorabsenergy[WHICHERROR]>IMPALLOWCONVCONSTABS){ failreturnenergy=FAILRETURNGENERAL; eomtypeenergy=EOMGRMHD; }
3958  else if(errorabsenergy[WHICHERROR]<IMPTRYCONVABS){ failreturnenergy=FAILRETURNNOFAIL; eomtypeenergy=EOMDIDGRMHD;}
3959  else{ failreturnenergy=FAILRETURNNOTTOLERROR; eomtypeenergy=EOMDIDGRMHD;}
3960  }
3961  else{ // else get new ramesh solution
3962  FTYPE errorabsforramesh[NUMERRORTYPES];
3963  set_array(errorabsforramesh,NUMERRORTYPES,MPI_FTYPE,1.0);
3964  // start fresh with ramesh
3965  if(errorabsenergy[WHICHERROR]>TRYHARDERFEEDGUESSTOL){
3966  if(ACTUALHARDFAILURE(failreturnentropy)==1 || errorabsentropy[WHICHERROR]>ERRORTOUSEENTROPYFORENERGYGUESS){
3967  PLOOP(pliter,pl){
3968  pbenergy[pl]=pbbackup[pl];
3969  uubenergy[pl]=uubbackup[pl];
3970  SCLOOP(sc) dUcompeng[sc][pl]=dUcompenergy[sc][pl]=dUcompbackup[sc][pl];
3971  }
3972  qenergy=qbackup;
3973  errorabseng[0]=errorabseng[1]=1.0;
3974  errorabsforramesh[0]=errorabsforramesh[1]=1.0;
3975  radinvmodeng=UTOPRIMRADFAILBAD1;
3976  }
3977  else{
3978  PLOOP(pliter,pl){
3979  pbenergy[pl]=pbentropy[pl];
3980  uubenergy[pl]=uubentropy[pl];
3981  SCLOOP(sc) dUcompeng[sc][pl]=dUcompenergy[sc][pl]=dUcompbackup[sc][pl];
3982  }
3983  qenergy=qentropy;
3984  errorabseng[0]=errorabsentropybest[0];
3985  errorabseng[1]=errorabsentropybest[1];
3986  errorabsforramesh[0]=errorabsforramesh[1]=1.0;
3987  radinvmodeng=radinvmodentropybest;
3988  }
3989  }
3990  else{
3991  PLOOP(pliter,pl){
3992  pbenergy[pl]=pbenergybest[pl];
3993  uubenergy[pl]=uubenergybest[pl];
3994  SCLOOP(sc) dUcompeng[sc][pl]=dUcompenergy[sc][pl]=dUcompbackup[sc][pl]; // always backup
3995  }
3996  qenergy=qenergybest;
3997  errorabseng[0]=errorabsenergybest[0];
3998  errorabseng[1]=errorabsenergybest[1];
3999  errorabsforramesh[0]=errorabsenergybest[0];
4000  errorabsforramesh[1]=errorabsenergybest[1];
4001  radinvmodeng=radinvmodenergybest;
4002  }
4003  //
4004  // BEGIN GET RAMESH SOLUTION
4005  failreturnenergy=FAILRETURNGENERAL;// default to fail
4006  eomtypeenergy=EOMGRMHD;
4007  int whichcall=eomtypeenergy;
4008  get_rameshsolution_wrapper(whichcall, eomtypeenergy, errorabsforramesh, ptrgeom, pbenergy, piin, Uiin, Ufin, dUother, CUf, CUimp, q, ppeng, ppent, uueng, uuent, dUcompeng, dUcompent, &qeng, &qent, &failtypeeng, errorabseng, &iterseng, &radinvmodeng, &failtypeent, errorabsent, &itersent, &radinvmodent);
4009  gotrameshsolution=1; // indicates did at least attempt ramesh soltion call
4010  // translate
4011  PLOOP(pliter,pl){
4012  pbenergy[pl]=ppeng[pl];
4013  uubenergy[pl]=uueng[pl];
4014  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompeng[sc][pl];
4015  }
4016  qenergy=qeng;
4017  //
4018  *lpflag=*lpflagrad=(PFTYPE)failtypeeng; // need better translation
4019  radinvmodenergy=radinvmodeng;
4020  radErfnegenergy=0; // not allowed, considered BADNEG type
4021  itersenergy=iterseng;
4022  errorabsenergy[0]=errorabseng[0];
4023  errorabsenergy[1]=errorabseng[1];
4024  if(failtypeeng || errorabsenergy[WHICHERROR]>IMPALLOWCONVCONSTABS){ failreturnenergy=FAILRETURNGENERAL; eomtypeenergy=EOMGRMHD; }
4025  else if(errorabsenergy[WHICHERROR]<IMPTRYCONVABS){ failreturnenergy=FAILRETURNNOFAIL; eomtypeenergy=EOMDIDGRMHD;}
4026  else{ failreturnenergy=FAILRETURNNOTTOLERROR; eomtypeenergy=EOMDIDGRMHD;}
4027  // END GET RAMESH SOLUTION
4028  }// end else if need to get ramesh solution
4029 
4030  // see if want to keep
4031  // if(errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && ACTUALHARDFAILURE(failreturnenergy)==0){// || failreturnenergy==FAILRETURNMODESWITCH){ // no switch mode in ramesh solver yet.
4032  // if((errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && (RADINVBAD(radinvmodenergy)==0 || RADINVBAD(radinvmodenergybest) && RADINVBAD(radinvmodenergy)) || RADINVBAD(radinvmodenergybest) && RADINVBAD(radinvmodenergy)==0 && (errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR]||errorabsenergy[WHICHERROR]<IMPOKCONVABS)) && ACTUALHARDFAILURE(failreturnenergy)==0){
4033 
4034  // if((errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && (RADINVBAD(radinvmodenergy)==0 || RADINVBAD(radinvmodenergybest) && RADINVBAD(radinvmodenergy)) || RADINVBAD(radinvmodenergybest) && RADINVBAD(radinvmodenergy)==0 && (errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR]||errorabsenergy[WHICHERROR]<IMPOKCONVABS) || RADINVBAD(radinvmodenergybest)==0 && RADINVBAD(radinvmodenergy) && (errorabsenergybest[WHICHERROR]>IMPOKCONVABS && errorabsenergy[WHICHERROR]<IMPOKCONVABS)) && ACTUALHARDFAILURE(failreturnenergy)==0){
4035 
4036  if(
4037  (
4038  // best and no radinv problem
4039  errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && RADINVBAD(radinvmodenergy)==0
4040  // best because prior best also had radinv problem and still smaller error
4041  || errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && (RADINVBAD(radinvmodenergy) && RADINVBAD(radinvmodenergybest))
4042  // best because even though has radinv problem (while best doesn't) much smaller error
4043  || errorabsenergy[WHICHERROR]<errorabsenergybest[WHICHERROR] && errorabsenergy[WHICHERROR]<IMPOKCONVABS && errorabsenergybest[WHICHERROR]>100.0*IMPOKCONVABS && (RADINVBAD(radinvmodenergy) && RADINVBAD(radinvmodenergybest)==0)
4044  )
4045  && ACTUALHARDFAILURE(failreturnenergy)==0){
4046 
4047  if(ACCEPTASNOFAILURE(failreturnenergy)) usedrameshenergy=1; // means will use this actually, not just best yet no good enough
4048  // store result in case better than latter results
4049  lpflagenergybest=*lpflag;
4050  lpflagradenergybest=*lpflagrad;
4051  radinvmodenergybest=radinvmodenergy;
4052  radErfnegenergybest=radErfnegenergy;
4053  failreturnenergybest=failreturnenergy;
4054  eomtypeenergybest=eomtypeenergy;
4055  errorabsenergybest[0]=errorabsenergy[0];
4056  errorabsenergybest[1]=errorabsenergy[1];
4057  PLOOP(pliter,pl){
4058  pbenergybest[pl]=pbenergy[pl];
4059  uubenergybest[pl]=uubenergy[pl];
4060  SCLOOP(sc) dUcompenergybest[sc][pl]=dUcompenergy[sc][pl];
4061  }
4062  qenergybest=qenergy;
4063 
4064  // save which method ended up using
4065  methodindex[BASEITERMETHODINDEX] = QTYPMHD;
4066  methodindex[ITERMODEINDEX] = ITERMODESTAGES;
4067  methodindex[IMPMAXITERINDEX] = IMPMAXITERLONG;
4068  methodindex[NUMDAMPINDEX] = NUMDAMPATTEMPTSQUICK;
4069  methodindex[MODPRIMINDEX] = 0;
4070  methodindex[CHECKRADINVINDEX] = 1;
4071  methodindex[EOMTYPEINDEX] = EOMGRMHD;
4072 
4073  }
4074 
4075  // still cost more iters
4076  itersenergy+=itersenergyold;
4077 
4078  if(ACTUALHARDORSOFTFAILURE(failreturnenergy)==0){// || failreturnenergy==FAILRETURNMODESWITCH){
4079  if(debugfail>=2) dualfprintf(fail_file,"(energy: failreturnenergy=%d): Recovered using ramesh (%d %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g iters: %d->%d\n",failreturnenergy,gotrameshsolution,usedrameshenergy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsenergyold[WHICHERROR],errorabsenergy[WHICHERROR],itersenergyold,itersenergy);
4080  }
4081  else{
4082  if(debugfail>=2) dualfprintf(fail_file,"Failed to (energy: failreturnenergy=%d): Recovered using ramesh (%d %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g iters: %d->%d\n",failreturnenergy,gotrameshsolution,usedrameshenergy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsenergyold[WHICHERROR],errorabsenergy[WHICHERROR],itersenergyold,itersenergy);
4083  }
4084  }// end if using ramesh
4085 
4086 
4087 
4088 
4089 
4090 
4092  //
4093  // use best result from trying harder over all energy attempts
4094  //
4096  *lpflag=lpflagenergybest;
4097  *lpflagrad=lpflagradenergybest;
4098  radinvmodenergy=radinvmodenergybest;
4099  radErfnegenergy=radErfnegenergybest;
4100  failreturnenergy=failreturnenergybest;
4101  eomtypeenergy=eomtypeenergybest;
4102  errorabsenergy[0]=errorabsenergybest[0];
4103  errorabsenergy[1]=errorabsenergybest[1];
4104  PLOOP(pliter,pl){
4105  pbenergy[pl]=pbenergybest[pl];
4106  uubenergy[pl]=uubenergybest[pl];
4107  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompenergybest[sc][pl];
4108  }
4109  qenergy=qenergybest;
4110  goexplicitenergy=goexplicitenergybest;
4111 
4112  // store these in case energy ultimately used
4113  lpflagenergy=*lpflag;
4114  lpflagradenergy=*lpflagrad;
4115 
4116 
4117 
4118 
4119 
4120 
4121  }// end if doing GRMHD inversion
4122  else{
4123  // if didn't do energy inversion, treat as failure of said inversion
4124  failreturnenergy=FAILRETURNGENERAL;
4125  }
4126 
4127 
4128 
4129 
4130 
4131 
4132 
4133  if(
4134  reducetoquick!=1 && (
4135  eomtypecond[EOMENTROPYGRMHD]==1
4136  || (pbenergy[UU]<=0.0 && ACCEPTASNOFAILURE(failreturnenergy)==1 || ACTUALHARDFAILURE(failreturnenergy)==1)
4137  )
4138  ){
4140  //
4141  // GET ENTROPY (currently, only if failure for energy solver)
4142  //
4144 
4145 
4146  // quickly try QTYPMHD then QTYURAD
4147  int tryphase1;
4148 
4149  int baseitermethodlist[NUMPHASESENT]={QTYPMHD,QTYENTROPYUMHD,QTYURAD,QTYPRAD,QTYPMHD,QTYENTROPYUMHD,QTYURAD,QTYPRAD}; int whichfirstpmhd=0,whichfirstentropyumhd=1,whichfirsturad=2,whichfirstprad=3;
4151 #if(DOPERF&&0) // superquick too little
4155  int trueimpmaxiterlist[NUMPHASESENT]={IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1,IMPMAXITERSUPERQUICK+1};
4156 #endif
4157 #if(DOPERF)
4162 #else
4167 #endif
4169  int modprimlist[NUMPHASESENT]={0,0,0,0,1,0,0,0};
4170  int checkradinvlist[NUMPHASESENT]={0,1,1,1,0,1,1,1};
4172 
4173  // results in list
4174  FTYPE errorabslist[NUMPHASES][NUMERRORTYPES];
4175  set_array(errorabslist,NUMPHASES*NUMERRORTYPES,MPI_FTYPE,1.0);
4176  int radinvmodlist[NUMPHASES];
4177  set_array(radinvmodlist,NUMPHASES,MPI_INT,UTOPRIMRADFAILBAD1);
4178 
4179  if(gasprimaryevolves==0){ // if gas primary evolves, then keep original order because PMHD is fastest method.
4180  if(radprimaryevolves){
4181  if(
4182  (USEPRIORITERMETHOD && (prioritermethodlist[BASEITERMETHODINDEX] == PRIORITERMETHODNOTSET || prioritermethodlist[BASEITERMETHODINDEX] == QTYURAD))
4183  || USEPRIORITERMETHOD==0
4184  ){
4185  tryphase1=-1;
4186  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0; whichfirsturad=tryphase1;
4187  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0; whichfirstprad=tryphase1;
4188  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=0; whichfirstpmhd=tryphase1;
4189  tryphase1++; baseitermethodlist[tryphase1]=QTYENTROPYUMHD; modprimlist[tryphase1]=0; whichfirstentropyumhd=tryphase1;
4190  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0;
4191  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0;
4192  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=1;
4193  tryphase1++; baseitermethodlist[tryphase1]=QTYENTROPYUMHD; modprimlist[tryphase1]=0;
4194  }
4195  if(
4196  (USEPRIORITERMETHOD && prioritermethodlist[BASEITERMETHODINDEX] == QTYPRAD)
4197  ){
4198  tryphase1=-1;
4199  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0; whichfirstprad=tryphase1;
4200  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0; whichfirsturad=tryphase1;
4201  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=0; whichfirstpmhd=tryphase1;
4202  tryphase1++; baseitermethodlist[tryphase1]=QTYENTROPYUMHD; modprimlist[tryphase1]=0; whichfirstentropyumhd=tryphase1;
4203  tryphase1++; baseitermethodlist[tryphase1]=QTYPRAD; modprimlist[tryphase1]=0;
4204  tryphase1++; baseitermethodlist[tryphase1]=QTYURAD; modprimlist[tryphase1]=0;
4205  tryphase1++; baseitermethodlist[tryphase1]=QTYPMHD; modprimlist[tryphase1]=1;
4206  tryphase1++; baseitermethodlist[tryphase1]=QTYENTROPYUMHD; modprimlist[tryphase1]=0;
4207  }
4208  }
4209  }
4210 
4211 
4212  int firsttryphase1used=-1;
4213  for(tryphase1=0;tryphase1<NUMPHASESENT;tryphase1++){
4214 
4215  // pick best simple method avoids all solvers except PMHD
4216  if(modemethodlocal==MODEPICKBESTSIMPLE && baseitermethodlist[tryphase1]!=QTYPMHD) continue;
4217 
4218 #if(DOPERF)
4219  // pick best simple 2 method avoids all itermodestages methods
4220  if(modemethodlocal==MODEPICKBESTSIMPLE && itermodelist[tryphase1]==ITERMODESTAGES) continue;
4221  if(funnelcond){ // then don't expect to treat density accurate anyways, just need ok accuracy and stability
4222  trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONVMARGINAL);
4223  }
4224  if(V[1]<Rhor && isbhspc){
4225  // trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONV_RHORHIGHERTOL);
4226  trueimpallowconvconstlist[tryphase1]=MAX(trueimpallowconvconstlist[tryphase1],IMPALLOWCONV_RHORHIGHERTOL);
4227  }
4228  else if(V[1]>OUTERDEATHRADIUS && OUTERDEATH==1){
4229  trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONV_ROUTERHIGHERTOL);
4230  }
4231 #else
4232  // pick best simple 2 method avoids all itermodestages methods
4233  if(modemethodlocal==MODEPICKBESTSIMPLE2 && itermodelist[tryphase1]==ITERMODESTAGES) continue;
4234 #endif
4235 
4236  // avoid method in case very non-dominant since then would give errorneous (critically bad even) results. If methods that can use fail, have to revert to entropy or fixups.
4237  if(radextremeprimaryevolves && (baseitermethodlist[tryphase1]==QTYPMHD || baseitermethodlist[tryphase1]==QTYENTROPYUMHD) ) continue;
4238  if(gasextremeprimaryevolves && (baseitermethodlist[tryphase1]==QTYURAD || baseitermethodlist[tryphase1]==QTYPRAD)) continue;
4239 
4240  if(radextremeprimaryevolves==0 && (baseitermethodlist[tryphase1]==QTYURAD || baseitermethodlist[tryphase1]==QTYPRAD) ){
4241  // if not in extreme radiative regime, then don't do damping for raditive schemes that are slow.
4242  truenumdampattemptslist[tryphase1]=NUMDAMPATTEMPTSQUICK;
4243  // and don't try to get too good of error.
4244  trueimptryconvlist[tryphase1]=IMPTRYCONVQUICK;
4245  // and avoid stages
4246  itermodelist[tryphase1]=ITERMODENORMAL;
4247  }
4248  if(gasextremeprimaryevolves==0 && (baseitermethodlist[tryphase1]==QTYPMHD)){
4249  // then still try to get good error since fast method, so no changes.
4250  }
4251 
4252 
4253  if(modemethodlocal==MODEPICKBESTSIMPLE){
4254  // do nothing, don't skip stages.
4255  }
4256  else{
4257  // If already tried QTYPMHD and that got error(0)<tol but error(1)>tol, then skip QTYPMHD with stages since should switch to QTYURAD or QTYPRAD because STAGES won't improve on error(1) if error(0)<tol.
4258  if(baseitermethodlist[tryphase1]==QTYPMHD && errorabslist[whichfirstpmhd][0]<IMPTRYCONV && errorabslist[whichfirstpmhd][1]>IMPTRYCONV && WHICHERROR==1){
4259  // then should skip this case and rely upon radiative solvers
4260  continue;
4261  }
4262 
4263  if(baseitermethodlist[tryphase1]==QTYENTROPYUMHD && errorabslist[whichfirstentropyumhd][0]<IMPTRYCONV && errorabslist[whichfirstentropyumhd][1]>IMPTRYCONV && WHICHERROR==1){
4264  // then should skip this case and rely upon others
4265  continue;
4266  }
4267 
4268  if(baseitermethodlist[tryphase1]==QTYURAD && errorabslist[whichfirsturad][0]<IMPTRYCONV && errorabslist[whichfirsturad][1]>IMPTRYCONV && WHICHERROR==1){
4269  // then should skip this case and rely upon others
4270  continue;
4271  }
4272 
4273  if(baseitermethodlist[tryphase1]==QTYPRAD && errorabslist[whichfirstprad][0]<IMPTRYCONV && errorabslist[whichfirstprad][1]>IMPTRYCONV && WHICHERROR==1){
4274  // then should skip this case and rely upon others
4275  continue;
4276  }
4277  }
4278 
4279 
4280  // __WORKINGONIT__
4281  //if(baseitermethodlist[tryphase1]==QTYENTROPYUMHD || baseitermethodlist[tryphase1]==QTYURAD || baseitermethodlist[tryphase1]==QTYPRAD) continue; // skip this method for now.
4282  if(baseitermethodlist[tryphase1]==QTYENTROPYUMHD) continue; // skip this method for now.
4283 
4284  if(reducetoquick){
4285  if(reducetoquick==1){
4286  trueimptryconvlist[tryphase1]=IMPTRYCONVSUPERQUICK;
4287  trueimpmaxiterlist[tryphase1]=1;
4288  }
4289  else{
4290  trueimptryconvlist[tryphase1]=IMPTRYCONVQUICK;
4291  trueimpmaxiterlist[tryphase1]=IMPMAXITERQUICK;
4292  }
4293  if(firsttryphase1used!=-1) continue;
4294  }
4295 
4296 
4297  // consider radinvmod only if error bad for original approach. Avoids excessive attempts when should hit radiative ceiling and error is small.
4298 
4299  int needtotry;
4300  needtotry=RADINVBAD(radinvmodentropybest) && checkradinvlist[tryphase1] || ACTUALHARDORSOFTFAILURE(failreturnentropybest) && failreturnentropybest!=FAILRETURNMODESWITCH;
4301 
4302  if(needtotry){
4303  if(firsttryphase1used==-1) firsttryphase1used=tryphase1;
4304  tryphaselistentropy[tryphase1]++;
4305 
4306 
4307  itersentropyold=itersentropy;
4308  errorabsentropyold[0]=errorabsentropy[0];
4309  errorabsentropyold[1]=errorabsentropy[1];
4310  radinvmodentropyold=radinvmodentropy;
4311  //
4312  whichcapentropy=CAPTYPEBASIC;
4313  baseitermethodentropy=baseitermethodlist[tryphase1];
4314  itermodeentropy=itermodelist[tryphase1];
4315  trueimptryconventropy=trueimptryconvlist[tryphase1];
4316  trueimpokconventropy=(MAX(trueimptryconvlist[tryphase1],trueimpokconvlist[tryphase1]));
4317  trueimpallowconventropy=(MAX(trueimptryconvlist[tryphase1],trueimpallowconvconstlist[tryphase1]));
4318  trueimpmaxiterentropy=trueimpmaxiterlist[tryphase1];
4319  truenumdampattemptsentropy=truenumdampattemptslist[tryphase1];
4320  int modprim=0;
4321  if(havebackup==0) modprim=modprimlist[tryphase1];
4322  //
4323  // start fresh
4324  *lpflag=UTOPRIMNOFAIL;
4325  *lpflagrad=UTOPRIMRADNOFAIL;
4326  radinvmodentropy=0;
4327  radErfnegentropy=0;
4328  failreturnentropy=FAILRETURNGENERAL;// default to fail
4329  eomtypeentropy=eomtypelist[tryphase1];
4330  errorabsentropy[0]=errorabsentropy[1]=1.0;
4331  //
4332  // setup guess
4333  if(ACTUALHARDFAILURE(failreturnenergy)==1 || errorabsenergy[WHICHERROR]>ERRORTOUSEENTROPYFORENERGYGUESS || pbenergy[UU]<=0.0){
4334  if(errorabsentropybest[WHICHERROR]>TRYHARDERFEEDGUESSTOL){
4335  PLOOP(pliter,pl){
4336  pbentropy[pl]=pbbackup[pl];
4337  uubentropy[pl]=uubbackup[pl];
4338  SCLOOP(sc) dUcompentropy[sc][pl]=dUcompbackup[sc][pl];
4339  }
4340  qentropy=qbackup;
4341  errorabsentropy[0]=errorabsentropy[1]=1.0;
4342  radinvmodentropy=UTOPRIMRADFAILBAD1;
4343  }
4344  else{
4345  PLOOP(pliter,pl){
4346  pbentropy[pl]=pbentropybest[pl];
4347  uubentropy[pl]=uubentropybest[pl];
4348  SCLOOP(sc) dUcompentropy[sc][pl]=dUcompbackup[sc][pl];
4349  }
4350  qentropy=qentropybest;
4351  errorabsentropy[0]=errorabsentropybest[0];
4352  errorabsentropy[1]=errorabsentropybest[1];
4353  radinvmodentropy=radinvmodentropybest;
4354  }
4355  }
4356  else{ // start with energy
4357  PLOOP(pliter,pl){
4358  pbentropy[pl]=pbenergy[pl];
4359  SCLOOP(sc) dUcompentropy[sc][pl]=dUcompbackup[sc][pl];
4360  }
4361  qentropy=qenergy;
4362  errorabsentropy[0]=errorabsenergy[0]; // just for setting guess, not accepted error for entropy
4363  errorabsentropy[1]=errorabsenergy[1]; // just for setting guess, not accepted error for entropy
4364  radinvmodentropy=radinvmodenergy;
4365  }
4366  //
4367  //
4368  FTYPE fracenergyentropy=0;
4369  failreturnentropy=koral_source_rad_implicit_mode(modemethodlocal,0,modprim,havebackup, didentropyalready, &eomtypeentropy, whichcapentropy, itermodeentropy, &baseitermethodentropy, trueimptryconventropy, trueimpokconventropy, trueimpallowconventropy, trueimpmaxiterentropy, truenumdampattemptsentropy, fracenergyentropy, dissmeasure, &radinvmodentropy, pbentropy, uubentropy, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, &qentropy, dUother ,dUcompentropy, errorabsentropy, errorabsentropybest, &itersentropy, &f1itersentropy, &nummhdinvsentropy, &nummhdstepsentropy);
4370  nummhdsteps+=nummhdstepsentropy;
4371 
4372 
4373  // store error, no matter if using solution or not or even if explicit
4374  errorabslist[tryphase1][0]=errorabsentropy[0];
4375  errorabslist[tryphase1][1]=errorabsentropy[1];
4376 
4377  if(failreturnentropy==FAILRETURNGOTRIVIALEXPLICIT){
4378  lpflagentropybest=*lpflag;
4379  lpflagradentropybest=*lpflagrad;
4380  radinvmodentropybest=radinvmodentropy;
4381  radErfnegentropybest=radErfnegentropy;
4382  failreturnentropybest=failreturnentropy;
4383  eomtypeentropybest=eomtypelist[tryphase1];
4384  goexplicitentropybest=1;
4385 
4386  // save which method ended up using
4387  int prioriter; for(prioriter=0;prioriter<NUMPRIORITERMETHODINDEX;prioriter++){
4388  methodindex[prioriter] = PRIORITERMETHODNOTSET; // back to unknown
4389  }
4390  }
4391  else{
4392  // see if want to keep
4393  // if((errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && (RADINVBAD(radinvmodentropy)==0 || RADINVBAD(radinvmodentropybest) && RADINVBAD(radinvmodentropy)) || RADINVBAD(radinvmodentropybest) && RADINVBAD(radinvmodentropy)==0 && (errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR]||errorabsentropy[WHICHERROR]<IMPOKCONVABS) || RADINVBAD(radinvmodentropybest)==0 && RADINVBAD(radinvmodentropy) && (errorabsentropybest[WHICHERROR]>IMPOKCONVABS && errorabsentropy[WHICHERROR]<IMPOKCONVABS)) && ACTUALHARDFAILURE(failreturnentropy)==0){
4394  if(
4395  (
4396  // best and no radinv problem
4397  errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && RADINVBAD(radinvmodentropy)==0
4398  // best because prior best also had radinv problem and still smaller error
4399  || errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && (RADINVBAD(radinvmodentropy) && RADINVBAD(radinvmodentropybest))
4400  // best because even though has radinv problem (while best doesn't) much smaller error
4401  || errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && errorabsentropy[WHICHERROR]<IMPOKCONVABS && errorabsentropybest[WHICHERROR]>100.0*IMPOKCONVABS && (RADINVBAD(radinvmodentropy) && RADINVBAD(radinvmodentropybest)==0)
4402  )
4403  && ACTUALHARDFAILURE(failreturnentropy)==0){
4404 
4405  // store result in case better than latter results
4406  lpflagentropybest=*lpflag;
4407  lpflagradentropybest=*lpflagrad;
4408  radinvmodentropybest=radinvmodentropy;
4409  radErfnegentropybest=radErfnegentropy;
4410  failreturnentropybest=failreturnentropy;
4411  eomtypeentropybest=eomtypeentropy;
4412  goexplicitentropybest=0;
4413  errorabsentropybest[0]=errorabsentropy[0];
4414  errorabsentropybest[1]=errorabsentropy[1];
4415  PLOOP(pliter,pl){
4416  pbentropybest[pl]=pbentropy[pl];
4417  uubentropybest[pl]=uubentropy[pl];
4418  SCLOOP(sc) dUcompentropybest[sc][pl]=dUcompentropy[sc][pl];
4419  }
4420  qentropybest=qentropy;
4421 
4422  // save which method ended up using
4423  methodindex[BASEITERMETHODINDEX] = baseitermethodlist[tryphase1];
4424  methodindex[ITERMODEINDEX] = itermodelist[tryphase1];
4425  methodindex[IMPTRYCONVINDEX] = (trueimptryconvlist[tryphase1]==IMPTRYCONV);
4426  methodindex[IMPMAXITERINDEX] = trueimpmaxiterlist[tryphase1];
4427  methodindex[NUMDAMPINDEX] = truenumdampattemptslist[tryphase1];
4428  methodindex[MODPRIMINDEX] = modprimlist[tryphase1];
4429  methodindex[CHECKRADINVINDEX] = checkradinvlist[tryphase1];
4430  methodindex[EOMTYPEINDEX] = eomtypelist[tryphase1];
4431 
4432  }
4433  }
4434 
4435  // regardless, still cost more iters
4436  itersentropy+=itersentropyold;
4437 
4438  int noproblem=ACTUALHARDORSOFTFAILURE(failreturnentropy)==0;
4439 
4440  if(tryphase1!=firsttryphase1used && noproblem){
4441  if(debugfail>=2) dualfprintf(fail_file,"Recovered using tryphase1=%d (entropy: %d radinvmod=%d -> %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g (best=%21.15g) iters: %d->%d\n",tryphase1,failreturnentropy,radinvmodentropyold,radinvmodentropy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsentropyold[WHICHERROR],errorabsentropy[WHICHERROR],errorabsentropybest[WHICHERROR],itersentropyold,itersentropy);
4442  }
4443  if(noproblem==0){
4444  if(debugfail>=2) dualfprintf(fail_file,"Failed to: <Recovered> using tryphase1=%d (entropy: %d radinvmod=%d -> %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g (best=%21.15g) iters: %d->%d\n",tryphase1,failreturnentropy,radinvmodentropyold,radinvmodentropy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsentropyold[WHICHERROR],errorabsentropy[WHICHERROR],errorabsentropybest[WHICHERROR],itersentropyold,itersentropy);
4445  }
4446 
4447  }// done trying harder
4448  }// end over tryphase1 loop
4449 
4450 
4451 
4452 
4453 
4454  if(
4455  !(modemethodlocal==MODEPICKBESTSIMPLE2) // Ramesh method is like stages, so avoid if simple2 method
4456  && ACTUALHARDORSOFTFAILURE(failreturnentropy) && USERAMESH && radextremeprimaryevolves==0
4457  && !(errorabslist[whichfirstpmhd][0]<IMPTRYCONV && errorabslist[whichfirstpmhd][1]>IMPTRYCONV)
4458  ){ // try ramesh
4459  errorabsentropyold[0]=errorabsentropy[0];
4460  errorabsentropyold[1]=errorabsentropy[1];
4461  radinvmodentropyold=radinvmodentropy;
4462  itersentropyold=itersentropy;
4463  goexplicitentropy=0; // doesn't check, so force implicit
4464  //
4465  //
4466  if(gotrameshsolution){// then just recall solution
4467  PLOOP(pliter,pl){
4468  pbenergy[pl]=ppeng[pl];
4469  uubenergy[pl]=uueng[pl];
4470  SCLOOP(sc) dUcompenergy[sc][pl]=dUcompeng[sc][pl];
4471  }
4472  qenergy=qeng;
4473  //
4474  *lpflag=*lpflagrad=(PFTYPE)failtypeeng; // need better translation
4475  radinvmodenergy=radinvmodeng;
4476  radErfnegenergy=0; // not allowed, considered BADNEG type
4477  itersenergy=iterseng;
4478  errorabsenergy[0]=errorabseng[0];
4479  errorabsenergy[1]=errorabseng[1];
4480  if(failtypeeng || errorabsenergy[WHICHERROR]>IMPALLOWCONVCONSTABS){ failreturnenergy=FAILRETURNGENERAL; eomtypeenergy=EOMGRMHD; }
4481  else if(errorabsenergy[WHICHERROR]<IMPTRYCONVABS){ failreturnenergy=FAILRETURNNOFAIL; eomtypeenergy=EOMDIDGRMHD;}
4482  else{ failreturnenergy=FAILRETURNNOTTOLERROR; eomtypeenergy=EOMDIDGRMHD;}
4483  }
4484  else{ // else get new ramesh solution
4485  FTYPE errorabsforramesh[NUMERRORTYPES];
4486  set_array(errorabsforramesh,NUMERRORTYPES,MPI_FTYPE,1.0);
4487  // start fresh with ramesh
4488  if(errorabsentropy[WHICHERROR]>TRYHARDERFEEDGUESSTOL){
4489  PLOOP(pliter,pl){
4490  pbentropy[pl]=pbbackup[pl];
4491  uubentropy[pl]=uubbackup[pl];
4492  SCLOOP(sc) dUcompent[sc][pl]=dUcompentropy[sc][pl]=dUcompbackup[sc][pl];
4493  }
4494  qentropy=qbackup;
4495  errorabsent[0]=errorabsent[1]=1.0;
4496  errorabsforramesh[0]=errorabsforramesh[1]=1.0;
4497  radinvmodent=UTOPRIMRADFAILBAD1;
4498  }
4499  else{
4500  PLOOP(pliter,pl){
4501  pbentropy[pl]=pbentropybest[pl];
4502  SCLOOP(sc) dUcompent[sc][pl]=dUcompentropy[sc][pl]=dUcompbackup[sc][pl]; // always backup
4503  }
4504  qentropy=qentropybest;
4505  errorabsforramesh[0]=errorabsentropybest[0];
4506  errorabsforramesh[1]=errorabsentropybest[1];
4507  errorabsent[0]=errorabsentropybest[0];
4508  errorabsent[1]=errorabsentropybest[1];
4509  radinvmodent=radinvmodentropybest;
4510  }
4511  //
4512  // BEGIN GET RAMESH SOLUTION
4513  failreturnentropy=FAILRETURNGENERAL;// default to fail
4514  eomtypeentropy=EOMENTROPYGRMHD;
4515  int whichcall=eomtypeentropy; // real entropy call
4516  get_rameshsolution_wrapper(whichcall, eomtypeentropy, errorabsforramesh, ptrgeom, pbentropy, piin, Uiin, Ufin, dUother, CUf, CUimp, q, ppeng, ppent, uueng, uuent, dUcompeng, dUcompent, &qeng, &qent, &failtypeeng, errorabseng, &iterseng, &radinvmodeng, &failtypeent, errorabsent, &itersent, &radinvmodent);
4517  gotrameshsolution=1; // indicates did at least attempt ramesh solution call
4518  // translate
4519  PLOOP(pliter,pl){
4520  pbentropy[pl]=ppent[pl];
4521  uubentropy[pl]=uuent[pl];
4522  SCLOOP(sc) dUcompentropy[sc][pl]=dUcompent[sc][pl];
4523  }
4524  qentropy=qent;
4525  //
4526  *lpflag=*lpflagrad=(PFTYPE)failtypeent; // need better translation
4527  radinvmodentropy=radinvmodent;
4528  radErfnegentropy=0; // not allowed, considered BADNEG type
4529  itersentropy=itersent;
4530  errorabsentropy[0]=errorabsent[0];
4531  errorabsentropy[1]=errorabsent[1];
4532  if(failtypeent || errorabsentropy[WHICHERROR]>IMPALLOWCONVCONSTABS){ failreturnentropy=FAILRETURNGENERAL; eomtypeentropy=EOMENTROPYGRMHD; }
4533  else if(errorabsentropy[WHICHERROR]<IMPTRYCONVABS){ failreturnentropy=FAILRETURNNOFAIL; eomtypeentropy=EOMDIDENTROPYGRMHD;}
4534  else{ failreturnentropy=FAILRETURNNOTTOLERROR; eomtypeentropy=EOMDIDENTROPYGRMHD;}
4535  // END GET RAMESH SOLUTION
4536  //
4537  }// end else if need to get ramesh solution
4538  // see if want to keep
4539  // if((errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && (RADINVBAD(radinvmodentropy)==0 || RADINVBAD(radinvmodentropybest) && RADINVBAD(radinvmodentropy)) || RADINVBAD(radinvmodentropybest) && RADINVBAD(radinvmodentropy)==0 && (errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR]||errorabsentropy[WHICHERROR]<IMPOKCONVABS) || RADINVBAD(radinvmodentropybest)==0 && RADINVBAD(radinvmodentropy) && (errorabsentropybest[WHICHERROR]>IMPOKCONVABS && errorabsentropy[WHICHERROR]<IMPOKCONVABS)) && ACTUALHARDFAILURE(failreturnentropy)==0){
4540  if(
4541  (
4542  // best and no radinv problem
4543  errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && RADINVBAD(radinvmodentropy)==0
4544  // best because prior best also had radinv problem and still smaller error
4545  || errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && (RADINVBAD(radinvmodentropy) && RADINVBAD(radinvmodentropybest))
4546  // best because even though has radinv problem (while best doesn't) much smaller error
4547  || errorabsentropy[WHICHERROR]<errorabsentropybest[WHICHERROR] && errorabsentropy[WHICHERROR]<IMPOKCONVABS && errorabsentropybest[WHICHERROR]>100.0*IMPOKCONVABS && (RADINVBAD(radinvmodentropy) && RADINVBAD(radinvmodentropybest)==0)
4548  )
4549  && ACTUALHARDFAILURE(failreturnentropy)==0){
4550 
4551  if(ACCEPTASNOFAILURE(failreturnentropy)) usedrameshentropy=1; // means will use this actually, not just best yet no good enough
4552  // store result in case better than latter results
4553  lpflagentropybest=*lpflag;
4554  lpflagradentropybest=*lpflagrad;
4555  radinvmodentropybest=radinvmodentropy;
4556  radErfnegentropybest=radErfnegentropy;
4557  failreturnentropybest=failreturnentropy;
4558  eomtypeentropybest=eomtypeentropy;
4559  errorabsentropybest[0]=errorabsentropy[0];
4560  errorabsentropybest[1]=errorabsentropy[1];
4561  PLOOP(pliter,pl){
4562  pbentropybest[pl]=pbentropy[pl];
4563  uubentropybest[pl]=uubentropy[pl];
4564  SCLOOP(sc) dUcompentropybest[sc][pl]=dUcompentropy[sc][pl];
4565  }
4566  qentropybest=qentropy;
4567 
4568  // save which method ended up using
4569  methodindex[BASEITERMETHODINDEX] = QTYPMHD;
4570  methodindex[ITERMODEINDEX] = ITERMODESTAGES;
4571  methodindex[IMPMAXITERINDEX] = IMPMAXITERLONG;
4572  methodindex[NUMDAMPINDEX] = NUMDAMPATTEMPTSQUICK;
4573  methodindex[MODPRIMINDEX] = 0;
4574  methodindex[CHECKRADINVINDEX] = 1;
4575  methodindex[EOMTYPEINDEX] = EOMENTROPYGRMHD;
4576 
4577  }
4578  // still cost more iters
4579  itersentropy+=itersentropyold;
4580  if(ACTUALHARDORSOFTFAILURE(failreturnentropy)==0){
4581  if(debugfail>=2) dualfprintf(fail_file,"Recovered using ramesh(%d) (entropy: radinvmod=%d -> %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g iters: %d->%d\n",failtypeent,radinvmodentropyold,radinvmodentropy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsentropyold[WHICHERROR],errorabsentropy[WHICHERROR],itersentropyold,itersentropy);
4582  }
4583  else{
4584  if(debugfail>=2) dualfprintf(fail_file,"Failed to: Recovered using ramesh(%d) (entropy: radinvmod=%d -> %d): ijknstepsteppart=%d %d %d %ld %d : error: %21.15g->%21.15g iters: %d->%d\n",failtypeent,radinvmodentropyold,radinvmodentropy,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,errorabsentropyold[WHICHERROR],errorabsentropy[WHICHERROR],itersentropyold,itersentropy);
4585  }
4586  }
4587 
4588 
4589 
4590 
4591 
4593  //
4594  // use best result
4595  //
4597  *lpflag=lpflagentropybest;
4598  *lpflagrad=lpflagradentropybest;
4599  radinvmodentropy=radinvmodentropybest;
4600  radErfnegentropy=radErfnegentropybest;
4601  failreturnentropy=failreturnentropybest;
4602  eomtypeentropy=eomtypeentropybest;
4603  errorabsentropy[0]=errorabsentropybest[0];
4604  errorabsentropy[1]=errorabsentropybest[1];
4605  PLOOP(pliter,pl){
4606  pbentropy[pl]=pbentropybest[pl];
4607  uubentropy[pl]=uubentropybest[pl];
4608  SCLOOP(sc) dUcompentropy[sc][pl]=dUcompentropybest[sc][pl];
4609  }
4610  qentropy=qentropybest;
4611  goexplicitentropy=goexplicitentropybest;
4612 
4613 
4614  // store these in case entropy ultimately used (if goexplicit, then these are set by last call to _mode() function)
4615  lpflagentropy=*lpflag;
4616  lpflagradentropy=*lpflagrad;
4617 
4618 
4619  // eomtypeentropy can become EOMDONOTHING if this call was successful
4620  }
4621  else{
4622  failreturnentropy=FAILRETURNGENERAL;// fail if wasn't done
4623  }
4624 
4625 
4626 
4627 
4628 
4629 
4630 
4631 
4632 
4633 
4634 
4636  //
4637  // See if want to try getting "cold" solution where only momentum exchange is considered
4638  //
4640 
4641 
4643  //
4644  // COLD VARIABLES
4645  //
4647 
4648  // holds iterations
4649  int iterscold=0;
4650  int f1iterscold=0;
4651  int nummhdinvscold=0;
4652  int nummhdstepscold=0;
4653 
4654  // implicit cold solution held in these variables
4655  FTYPE pbcold[NPR]; PLOOP(pliter,pl) pbcold[pl]=pbbackup[pl];
4656  FTYPE uubcold[NPR]; PLOOP(pliter,pl) uubcold[pl]=uubbackup[pl]; // holds returned uu from implicit solver
4657  FTYPE dUcompcold[NUMSOURCES][NPR]; PLOOP(pliter,pl) SCLOOP(sc) dUcompcold[sc][pl]=dUcompbackup[sc][pl];
4658  struct of_state qcold=qbackup;
4659  PFTYPE lpflagcold=1;
4660  PFTYPE lpflagradcold=1;
4661  int radinvmodcold=UTOPRIMRADFAILBAD1;
4662  int radErfnegcold=1;
4663  int failreturncold=FAILRETURNGENERAL; // default to fail in case cold not to be done at all
4664  int eomtypecold=EOMCOLDGRMHD;
4665  FTYPE errorabscold[NUMERRORTYPES];
4666  set_array(errorabscold,NUMERRORTYPES,MPI_FTYPE,1.0);
4667  int goexplicitcold=0;
4668 
4669 
4670  // try cold if energy and entropy both failed or the successfully converged versions gave u_g<=0.0
4671  if( reducetoquick!=1 && (
4672  (pbenergy[UU]<=0.0 && ACCEPTASNOFAILURE(failreturnenergy)==1 || ACCEPTASNOFAILURE(failreturnenergy)==0)
4673  &&
4674  (pbentropy[UU]<=0.0 && ACCEPTASNOFAILURE(failreturnentropy)==1 || ACCEPTASNOFAILURE(failreturnentropy)==0)
4675  )
4676  ){
4677 
4679  //
4680  // measure whether flow really cold enough to even use cold inversion
4681  //
4683  int includerad=1;
4684  FTYPE COLDFACTOR=0.1; // really ensure cold to use cold solution
4685  int iscoldflow=isflowcold(COLDFACTOR, includerad,pb,ptrgeom,q,uu0);
4686  // iscoldflow=1; // test
4687 
4688  // dualfprintf(fail_file,"iscoldflow: %d : ug=%21.15g Erf=%21.15g rhovsq=%21.15g : Esqgas=%21.15g usqgas=%21.15g Esqrad=%21.15g usqrad=%21.15g\n",iscoldflow,pb[UU],pb[URAD0],pb[RHO]*fabs(usq),fabs(ucongas[TT]*ucovgas[TT]),fabs(ugas),fabs(uconrad[TT]*ucovrad[TT]),fabs(urad)); // DEBUG
4689 
4690 
4691  // if flow is cold, do inversion
4692  if(iscoldflow==1){
4693 
4694  // count attempt to use cold
4695  tryphaselistcold[0]++;
4696 
4697  failreturncold=FAILRETURNGENERAL; // if doing cold, default is fail.
4698  int whichcapcold=CAPTYPEBASIC;
4699  int itermodecold=ITERMODECOLD;
4700  int baseitermethodcold=QTYPMHD;
4701 #if(DOPERF&&0) // superquick too little
4702  FTYPE trueimptryconvcold=IMPTRYCONVSUPERQUICK;
4703  FTYPE trueimpokconvcold=IMPALLOWCONVCONST;
4704  FTYPE trueimpallowconvcold=IMPALLOWCONVCONST;
4705  int trueimpmaxitercold=IMPMAXITERSUPERQUICK+1;
4706  int truenumdampattemptscold=NUMDAMPATTEMPTSQUICK;
4707 #else
4708  FTYPE trueimptryconvcold=IMPTRYCONVQUICK;
4709  FTYPE trueimpokconvcold=IMPALLOWCONVCONST;
4710  FTYPE trueimpallowconvcold=IMPALLOWCONVCONST;
4711  int trueimpmaxitercold=IMPMAXITERQUICK;
4712  int truenumdampattemptscold=NUMDAMPATTEMPTSQUICK;
4713 #endif
4714 
4715  if(funnelcond){ // then don't expect to treat density accurate anyways, just need ok accuracy and stability
4716  trueimptryconvcold=MAX(trueimptryconvcold,IMPTRYCONVMARGINAL);
4717  if(V[1]<Rhor && isbhspc){
4718  // trueimptryconvlist[tryphase1]=MAX(trueimptryconvlist[tryphase1],IMPTRYCONV_RHORHIGHERTOL);
4719  trueimpallowconvcold=MAX(trueimpallowconvcold,IMPALLOWCONV_RHORHIGHERTOL);
4720  }
4721  else if(V[1]>OUTERDEATHRADIUS && OUTERDEATH==1){
4722  trueimptryconvcold=MAX(trueimptryconvcold,IMPTRYCONV_ROUTERHIGHERTOL);
4723  }
4724 
4725  }
4726 
4727  if(reducetoquick){
4728  if(reducetoquick==1){
4729  trueimptryconvcold=IMPTRYCONVSUPERQUICK;
4730  trueimpmaxitercold=1;
4731  }
4732  else{
4733  trueimptryconvcold=IMPTRYCONVQUICK;
4734  trueimpmaxitercold=IMPMAXITERQUICK;
4735  }
4736  }
4737 
4738  // start fresh or use entropy as starting point
4739  *lpflag=UTOPRIMNOFAIL;
4740  *lpflagrad=UTOPRIMRADNOFAIL;
4741  radinvmodcold=0;
4742  radErfnegcold=0;
4743  failreturncold=FAILRETURNGENERAL; // default to fail in case cold not to be done at all
4744  eomtypecold=EOMCOLDGRMHD;
4745  goexplicitcold=0;
4746  errorabscold[0]=errorabscold[1]=1.0;
4747  FTYPE fracenergycold=0.0;
4748  FTYPE errorabscoldbest[NUMERRORTYPES];
4749  set_array(errorabscoldbest,NUMERRORTYPES,MPI_FTYPE,1.0);
4750 
4751  havebackup=0; // no backup since entropy and energy failed
4752  didentropyalready=0;
4753  PLOOP(pliter,pl){
4754  pbcold[pl]=pbbackup[pl];
4755  uubcold[pl]=uubbackup[pl];
4756  if(0){
4757  // but force cold setup
4758  pbcold[UU]=UUMINLIMIT;
4759  pbcold[URAD0]=ERADLIMIT;
4760  }
4761  else{
4762  // try just using static u_g and solving momentum equation as if not changing.
4763  }
4764  SCLOOP(sc) dUcompcold[sc][pl]=dUcompbackup[sc][pl];
4765  }
4766  qcold=qbackup;
4767  errorabscold[0]=errorabscold[1]=1.0;
4768 
4769 
4770  failreturncold=koral_source_rad_implicit_mode(modemethodlocal,0,0,havebackup, didentropyalready, &eomtypecold, whichcapcold, itermodecold, &baseitermethodcold, trueimptryconvcold, trueimpokconvcold, trueimpallowconvcold, trueimpmaxitercold, truenumdampattemptscold, fracenergycold, dissmeasure, &radinvmodcold, pbcold, uubcold, piin, Uiin, Ufin, CUf, CUimp, ptrgeom, &qcold, dUother ,dUcompcold, errorabscold, errorabscoldbest, &iterscold, &f1iterscold, &nummhdinvscold, &nummhdstepscold);
4771  nummhdsteps+=nummhdstepscold;
4772 
4773  if(failreturncold==FAILRETURNGOTRIVIALEXPLICIT) goexplicitcold=1;
4774  // store these in case cold ultimately used
4775  lpflagcold=*lpflag;
4776  lpflagradcold=*lpflagrad;
4777 
4778  // save which method ended up using
4779  methodindex[BASEITERMETHODINDEX] = QTYPMHD;
4780  methodindex[ITERMODEINDEX] = ITERMODECOLD;
4781  methodindex[IMPMAXITERINDEX] = IMPMAXITERQUICK;
4782  methodindex[NUMDAMPINDEX] = NUMDAMPATTEMPTS;
4783  methodindex[MODPRIMINDEX] = 0;
4784  methodindex[CHECKRADINVINDEX] = 1;
4785  methodindex[EOMTYPEINDEX] = EOMCOLDGRMHD;
4786 
4787 
4788  }// end if cold flow
4789  }// end if not failure
4790 
4791 
4792 
4793 
4794 
4795 
4796 
4797 
4798 
4799 
4800 
4801 
4803  //
4804  // see if should use the entropy solution
4805  //
4806  // Conditions to use entropy include:
4807  // 1) dissmeasure says should avoid energy
4808  // 2) energy failed
4809  // 3) energy predicts smaller u_g than entropy
4810  // 4) error in energy is large
4811  // 5) etc.
4812  // but keep changing conditions as learn more..
4813  //
4815 
4816  int doentropy=whetherdoentropy(ptrgeom, fracenergy, ACCEPTASNOFAILURE(failreturnentropy),ACCEPTASNOFAILURE(failreturnenergy), radinvmodentropy, radinvmodenergy, IMPTRYCONVABS, IMPOKCONVABS, IMPBADENERGY, errorabsentropy[WHICHERROR], errorabsenergy[WHICHERROR], pbentropy, pbenergy);
4817  if(goexplicitentropy==1) doentropy=0; // override
4818 
4819 
4820 
4821 
4822  // check if doing implicit
4823  // 1) check if used entropy
4824  // 2) check if used energy
4825  // 3) check if used cold
4826  // 4) else if none, then no implicit solution
4827 
4828  // 4a) If goexplicit{energy,entropy}=1, then explicit will be done as indicated by failfinalreturn=-1
4829  // 4b) Else, real failure, so will just avoid G and do outer MHD/RAD inversion that assumes G=0.
4830 
4831  if(goexplicitentropy==0 && goexplicitenergy==0){
4832  usedimplicit=1;
4833 
4835  //
4836  // cases where must use entropy
4837  //
4839  if(doentropy){
4840  // dualfprintf(fail_file,"USING ENTROPY\n");
4841  // tell an externals to switch to entropy
4842  // store these in case energy ultimately used
4843  *lpflag=lpflagentropy;
4844  *lpflagrad=lpflagradentropy;
4845  *eomtype=eomtypeentropy; // can be EOMDONOTHING if successful and small enough error
4846  // set result as entropy result
4847  PLOOP(pliter,pl){
4848  pb[pl]=pbentropy[pl];
4849  uub[pl]=uubentropy[pl];
4850  SCLOOP(sc) dUcomp[sc][pl]=dUcompentropy[sc][pl];
4851  *q=qentropy;
4852  }
4853  usedentropy=1;
4854  noprims=0;
4855  errorabs[0]=errorabsentropy[0];
4856  errorabs[1]=errorabsentropy[1];
4857  iters=itersentropy+itersenergy; // count both since did both
4858  f1iters=f1itersentropy+f1itersenergy; // count both since did both
4859  failreturn=failreturnentropy;
4860  failfinalreturn=0;
4861 
4862  // save
4863  methodindex[EOMTYPEINDEX] = EOMENTROPYGRMHD;
4864 
4865  }
4866  else if(ACCEPTASNOFAILURE(failreturnenergy)==1){ // automatically also done when fracenergy==1.0 (now, or when also fracenergy>0.0)
4867  // dualfprintf(fail_file,"USING ENERGY: errorabsenergy=%g errorabsentropy=%g\n",errorabsenergy[WHICHERROR],errorabsentropy[WHICHERROR]);
4868  *lpflag=lpflagenergy;
4869  *lpflagrad=lpflagradenergy;
4870  *eomtype=eomtypeenergy; // can be EOMDONOTHING if successful
4871  // set result as energy result
4872  PLOOP(pliter,pl){
4873  pb[pl]=pbenergy[pl];
4874  uub[pl]=uubenergy[pl];
4875  SCLOOP(sc) dUcomp[sc][pl]=dUcompenergy[sc][pl];
4876  *q=qenergy;
4877  }
4878  usedenergy=1;
4879  noprims=0;
4880  errorabs[0]=errorabsenergy[0];
4881  errorabs[1]=errorabsenergy[1];
4882  iters=itersentropy+itersenergy; // count both since did both
4883  f1iters=f1itersentropy+f1itersenergy; // count both since did both
4884  failreturn=failreturnenergy;
4885  failfinalreturn=0;
4886 
4887  // save
4888  methodindex[EOMTYPEINDEX] = EOMGRMHD;
4889 
4890  }
4891  else if(ACCEPTASNOFAILURE(failreturncold)==1){
4892  // dualfprintf(fail_file,"USING COLD: errorabscold=%g errorabsentropy=%g\n",errorabscold[WHICHERROR],errorabsentropy[WHICHERROR]);
4893  *lpflag=lpflagcold;
4894  *lpflagrad=lpflagradcold;
4895  *eomtype=eomtypecold; // can be EOMDONOTHING if successful
4896  // set result as cold result
4897  PLOOP(pliter,pl){
4898  pb[pl]=pbcold[pl];
4899  uub[pl]=uubcold[pl];
4900  SCLOOP(sc) dUcomp[sc][pl]=dUcompcold[sc][pl];
4901  *q=qcold;
4902  }
4903  usedcold=1;
4904  noprims=0;
4905  errorabs[0]=errorabscold[0];
4906  errorabs[1]=errorabscold[1];
4907  iters=itersentropy+itersenergy+iterscold; // count all since did all
4908  f1iters=f1itersentropy+f1itersenergy+f1iterscold; // ""
4909  failreturn=failreturncold;
4910  failfinalreturn=0;
4911 
4912  // need to fail on u_g and Erf so averages
4913  *lpflag=UTOPRIMFAILU2AVG1FROMCOLD;
4914  *lpflagrad=UTOPRIMFAILU2AVG1FROMCOLD;
4915  // only keep u_g and Erf static as backup
4916  pbcold[UU]=pbbackup[UU];
4917  pbcold[URAD0]=pbbackup[URAD0];
4918 
4919  // save
4920  methodindex[EOMTYPEINDEX] = EOMCOLDGRMHD;
4921 
4922  }
4923  else{ // force even if was default
4924  usedimplicit=0;
4925 
4926  // save
4927  methodindex[EOMTYPEINDEX] = EOMDEFAULT;
4928 
4929  }
4930  }
4931 
4932 
4933 
4934  if(usedimplicit==0){// No source either because goexplicitenergy==1 && goexplicitentropy==1 or failed
4935  if(goexplicitenergy==1 || goexplicitentropy==1){
4936  *lpflag=UTOPRIMNOFAIL;
4937  *lpflagrad=UTOPRIMRADNOFAIL;
4938  noprims=1;
4939  failfinalreturn=1;
4940  *eomtype=EOMDEFAULT;
4941  methodindex[EOMTYPEINDEX] = *eomtype;
4942 
4943  if(goexplicitenergy==1 || goexplicitentropy==1){ usedexplicitgood=1; failfinalreturn=FAILRETURNGOTRIVIALEXPLICIT;}
4944  else{ usedexplicitkindabad=1; failfinalreturn=1;} // __WORKINGONIT__: might want to treat as actual failure if QTYPMHD mode since lpflag never set.
4945 
4946  prod0dualfprintf(debugfail>=3,fail_file,"Went explicit: eenergy=%g eentropy=%g ienergy=%d ientropy=%d\n",errorabsenergy[WHICHERROR],errorabsentropy[WHICHERROR],itersenergy,itersentropy);
4947  }
4948  else if(*lpflagrad>UTOPRIMRADNOFAIL && *lpflag==UTOPRIMNOFAIL){ // then assume just radinvmod (i.e. any radiation failure is always fixable), so revert to explicit if couldn't find solution.
4949  *lpflag=UTOPRIMNOFAIL;
4950  // *lpflagrad=UTOPRIMRADNOFAIL;
4951  noprims=1; // so will apply fixup_utoprim()
4952  failfinalreturn=1;
4953  *eomtype=EOMDEFAULT;
4954  methodindex[EOMTYPEINDEX] = *eomtype;
4955 
4956  if(goexplicitenergy==1 || goexplicitentropy==1){ usedexplicitgood=1; failfinalreturn=FAILRETURNGOTRIVIALEXPLICIT;}
4957  else{ usedexplicitkindabad=1; failfinalreturn=1;} // __WORKINGONIT__: might want to treat as actual failure if QTYPMHD mode since lpflag never set.
4958 
4959  prod0dualfprintf(debugfail>=3,fail_file,"Went explicit: eenergy=%g eentropy=%g ienergy=%d ientropy=%d\n",errorabsenergy[WHICHERROR],errorabsentropy[WHICHERROR],itersenergy,itersentropy);
4960  }
4961  else{ // actual full failure
4962  // if no source, then will do normal inversion (no change to *eomtype) as if G=0.
4963  methodindex[EOMTYPEINDEX] = *eomtype;
4964  *lpflag=UTOPRIMFAILCONV;
4965  *lpflagrad=UTOPRIMRADFAILCASE1A;
4966  if(errorabsenergy[WHICHERROR]<errorabsentropy[WHICHERROR]){
4967  // indicates error that could have had if chose to raise IMPALLOWCONV
4968  errorabs[0]=errorabsenergy[0];
4969  errorabs[1]=errorabsenergy[1];
4970  }
4971  else{
4972  errorabs[0]=errorabsentropy[0];
4973  errorabs[1]=errorabsentropy[1];
4974  }
4975  failfinalreturn=1;
4976  if(reducetoquick!=1) usedexplicitbad=1;
4977 
4978  prod0dualfprintf(debugfail>=2,fail_file,"No source: eenergy=%g eentropy=%g ienergy=%d ientropy=%d\n",errorabsenergy[WHICHERROR],errorabsentropy[WHICHERROR],itersenergy,itersentropy);
4979  }
4980 
4981  // set prims and dU, but shouldn't be used
4982  PLOOP(pliter,pl){
4983  pb[pl]=pbbackup[pl];
4984  uub[pl]=uubbackup[pl];
4985  SCLOOP(sc) dUcomp[sc][pl]=dUcompbackup[sc][pl];
4986  *q=qbackup;
4987  }
4988  noprims=1;
4989  iters=itersentropy+itersenergy; // count both since did both
4990  f1iters=f1itersentropy+f1itersenergy; // count both since did both
4991  // failreturn=0;
4992  // KORALTODO: But might want to fail more aggressively and report total failure. Need to have estimate of whether G was important.
4993  failreturn=failreturnenergy;
4994  } // end if using implicit solution
4995 
4996 
4997  prod0dualfprintf(*eomtype>=0 && failreturnenergy>=0 && failreturnentropy>=0 && failreturncold>=0,fail_file,"WTF: %d %d %d : %d : %d : %d\n",failreturnentropy,failreturnenergy,failreturncold,failfinalreturn,noprims,*eomtype);
4998 
4999  }// end MODEPICKBEST || MODEPICKBESTSIMPLE || MODEPICKBESTSIMPLE2
5000 
5001 
5002 
5003  // DEBUG:
5004  // int prioriter; for(prioriter=0;prioriter<NUMPRIORITERMETHODINDEX;prioriter++){
5005  // dualfprintf(fail_file,"INDEX: prioriter=%d : %d\n",prioriter,methodindex[prioriter]);
5006  // }
5007 
5008 
5009 
5010 
5011 
5012 
5013  // whether set some primitives (implies also failfinalreturn=0)
5014  if(noprims==0){
5015  if((pb[RHO]<=0.)&&(pb[UU]>=0.)) *lpflag= UTOPRIMFAILRHONEG;
5016  if((pb[RHO]>0.)&&(pb[UU]<0.)) *lpflag= UTOPRIMFAILUNEG;
5017  if((pb[RHO]<=0.)&&(pb[UU]<0.)) *lpflag= UTOPRIMFAILRHOUNEG;
5018  if(pb[PRAD0]<=0.) *lpflagrad = UTOPRIMRADFAILERFNEG;
5019  }
5020 
5021 
5022  // force field to evolve as directly.
5023  PLOOPBONLY(pl){
5024  pf[pl]=pb[pl]=uu0[pl];
5025  dUcomp[RADSOURCE][pl]=0.0; // always has to be.
5026  }
5027 
5028 
5029 
5030  // DEBUG:
5031  // failfinalreturn=1;
5032  // *eomtype=EOMGRMHD;
5033 
5034 
5035 
5036 #if(PRODUCTION==0)
5037  // check if uncaught nan/inf
5038  int caughtnan=0;
5039  PLOOPDYNAMICAL(pliter,pl){
5040  if(!isfinite(pb[pl])) caughtnan++;
5041  if(!isfinite(pf[pl])) caughtnan++;
5042  if(!isfinite(uub[pl])) caughtnan++;
5043  if(!isfinite(dUcomp[RADSOURCE][pl])) caughtnan++;
5044  }
5045  if(caughtnan){
5046  // Doesn't seem to happen, even on Kraken
5047  if(debugfail>=2){
5048  dualfprintf(fail_file,"implicit solver generated nan result and it wasn't caught\n");
5049  PLOOPDYNAMICAL(pliter,pl) dualfprintf(fail_file,"1implicit solver: pl=%d pb=%21.15g pf=%21.15g dU=%21.15g\n",pl,pb[pl],pf[pl],dUcomp[RADSOURCE][pl]);
5050  int jj;
5051  DLOOPA(jj) dualfprintf(fail_file,"2implicit solver: jj=%d ucon=%21.15g ucov=%21.15g uradcon=%21.15g uradcov=%21.15g\n",jj,q->ucon[jj],q->ucov[jj],q->uradcon[jj],q->uradcov[jj]);
5052  }
5053 
5054  // choose as bad solution
5055 
5056  // if no source, then will do normal inversion (no change to *eomtype) as if G=0.
5057  methodindex[EOMTYPEINDEX] = *eomtype;
5058  *lpflag=UTOPRIMFAILCONV;
5059  *lpflagrad=UTOPRIMRADFAILCASE1A;
5060  if(debugfail>=2) dualfprintf(fail_file,"No sourceNAN\n");
5061  failfinalreturn=1;
5062  if(reducetoquick!=1) usedexplicitbad=1; // don't include as real bad failure if forced pass-through without real solution
5063 
5064  // set prims and dU, but shouldn't be used
5065  PLOOP(pliter,pl){
5066  pb[pl]=pbbackup[pl];
5067  uub[pl]=uubbackup[pl];
5068  SCLOOP(sc) dUcomp[sc][pl]=dUcompbackup[sc][pl];
5069  *q=qbackup;
5070  }
5071  noprims=1;
5072  // failreturn=0;
5073  }
5074 #endif
5075 
5076 
5077 
5078 
5079 
5080 
5081  {// save prior iter method
5082  int oo;
5083  for(oo=0;oo<NUMPRIORITERMETHODINDEX;oo++){
5084  GLOBALMACP0A1(prioritermethod,i,j,k,oo)=methodindex[oo];
5085  }
5086  }
5087 
5088 
5089 
5090 
5091 
5092 
5093 
5095  // DEBUG INFO STUFF
5096 
5097 
5098 
5099 #if(PRODUCTION==0)
5100  if(errorabs[WHICHERROR]>IMPALLOWCONVCONSTABS && (usedenergy||usedentropy||usedcold)){
5101  dualfprintf(fail_file,"WTF2: %g : %d %d %d : %d %d\n",errorabs[WHICHERROR],usedenergy,usedentropy,usedcold,usedrameshenergy,usedrameshentropy);
5102  myexit(666);
5103  }
5104 #endif
5105 
5106 
5107  int finalstep=steppart==TIMEORDER-1; // all sub-steps aren't a concern as just setting flux but not implicit part of final ucum
5108 
5109  // if(*lpflagrad<0){
5110  // dualfprintf(fail_file,"GOTHERE\n");
5111  // }
5112 
5113  // if(*lpflag<=UTOPRIMNOFAIL && *lpflagrad<=UTOPRIMRADNOFAIL && (! (*lpflag<UTOPRIMNOFAIL && *lpflagrad<UTOPRIMRADNOFAIL)) && finalstep==1 && failfinalreturn==0 && *eomtype==EOMDIDGRMHD && EOMTYPE==EOMGRMHD){
5114  //*lpflag<=UTOPRIMNOFAIL && *lpflagrad<=UTOPRIMRADNOFAIL && (! (*lpflag<UTOPRIMNOFAIL && *lpflagrad<UTOPRIMRADNOFAIL))&&
5115 
5116 
5117 
5118  if(finalstep==1&& failfinalreturn==0){
5119  // see how accurately got energy-momentum
5120  struct of_state qb;
5121  get_state(pb,ptrgeom,&qb);
5122  FTYPE ub[NPR],ubabs[NPR];
5123  int uutype=UDIAG;
5124  primtoU(uutype,pb,&qb,ptrgeom,ub,ubabs);
5125  // if((startpos[1]+ptrgeom->i==17) && (startpos[2]+ptrgeom->j)==0){
5126  // dualfprintf(fail_file,"URHOINIMPLICIT=%21.15g\n",ub[RHO]*dx[1]*dx[2]*dx[3]);
5127  // }
5128 
5129  FTYPE utot[NPR];
5130  PLOOP(pliter,pl) utot[pl] = uub[pl]; // UNOTHING
5131 
5132  // dualfprintf(fail_file,"ub=%g utot=%g dU=%g\n",ub[UU],utot[UU],ub[UU]-utot[UU]);
5133 
5134  FTYPE ubdiag[NPR],utotdiag[NPR];
5135  UtoU(UDIAG,UDIAG,ptrgeom,ub,ubdiag); // convert from UNOTHING -> UDIAG
5136  UtoU(UNOTHING,UDIAG,ptrgeom,utot,utotdiag); // convert from UNOTHING -> UDIAG
5137 
5138 
5139  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.
5140 
5141  // Get deltaUavg[] and also modify ucons if required and should
5142  int whocalled;
5143  if(usedenergy) whocalled=COUNTIMPLICITENERGY;
5144  else if(usedentropy) whocalled=COUNTIMPLICITENTROPY;
5145  else if(usedcold) whocalled=COUNTIMPLICITCOLDMHD;
5146  //else if(usedexplicitgood) whocalled=COUNTEXPLICITNORMAL;
5147  else if(usedexplicitkindabad || usedexplicitbad) whocalled=COUNTEXPLICITBAD;
5148  else if(usedenergy==0 && usedentropy==0 && usedboth==0 && usedcold==0 && usedimplicit==1) whocalled=COUNTIMPLICITBAD;
5149  else{
5150  // dualfprintf(fail_file,"GOD: %d %d\n",usedimplicit,usedexplicitgood);
5151  whocalled=COUNTIMPLICITITERS;
5152  }
5153 
5154  int docorrectuconslocal=0;
5155  extern int diag_fixup_dUandaccount(FTYPE *Ui, FTYPE *Uf, FTYPE *ucons, struct of_geom *ptrgeom, int finalstep, int whocalled, int docorrectuconslocal);
5156  diag_fixup_dUandaccount(utotdiag, ubdiag, NULL, ptrgeom, finalstep, whocalled, docorrectuconslocal);
5157 
5158 
5159  // FTYPE rat = fabs(utotdiag[RHO]-ubdiag[RHO])/(fabs(utotdiag[RHO])+fabs(ubdiag[RHO]));
5160  // if(rat>1E-13){
5161  // 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]);
5162  // }
5163 
5164  }
5165  else{
5166  // no solution, reverst to explicit and then average bad values, accounting will occur there.
5167  }
5168 
5169 
5170  if(DODEBUG){
5171  // counters for implicit method and how it fails.
5172  // Separate from normal utoprim inversion failure since once outside lose what actually did exactly
5173  // That is, once outside this function, only know if failed, not which scheme used, because locally treat as not failing if (e.g.) entropy or coldMHD can be used and they did not fail. This way, only no solution gives failure that then needs to be processed by fixup_utoprim().
5174 
5175  // just count, assume if want more details about how U is changed as a result, would use ONESTEPDUACCOUNTING=1
5176  extern int count_whocalled(int i, int j, int k, int finalstep, int whocalled, CTYPE toadd);
5177  int fakefinalstep=1; // always count, since final step actually doesn't do implicit stepping sometimes and need to know how intermediate steps did.
5178 
5179  count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITITERS,(CTYPE)iters);
5180  count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITMHDSTEPS,(CTYPE)nummhdsteps);
5181  count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITERRORS0,(CTYPE)errorabs[0]);
5182  count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITERRORS1,(CTYPE)errorabs[1]);
5183 
5184  if(usedimplicit) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITNORMAL,1);
5185  if(usedexplicitgood) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTEXPLICITNORMAL,1);
5186  if(usedexplicitkindabad || usedexplicitbad) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTEXPLICITBAD,1);
5187  if(usedenergy==0 && usedentropy==0 && usedboth==0 && usedcold==0 && usedimplicit==1) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITBAD,1);
5188  if(usedenergy||usedboth) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITENERGY,1);
5189  if(usedentropy||usedboth) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITENTROPY,1);
5190  if(usedcold) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITCOLDMHD,1);
5191 
5192 
5193 
5194  if(methodindex[BASEITERMETHODINDEX] == QTYPMHD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITPMHD,1);
5195  if(methodindex[BASEITERMETHODINDEX] == QTYUMHD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITUMHD,1);
5196  if(methodindex[BASEITERMETHODINDEX] == QTYPRAD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITPRAD,1);
5197  if(methodindex[BASEITERMETHODINDEX] == QTYURAD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITURAD,1);
5198  if(methodindex[BASEITERMETHODINDEX] == QTYENTROPYUMHD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITENTROPYUMHD,1);
5199  if(methodindex[BASEITERMETHODINDEX] == QTYENTROPYPMHD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITENTROPYPMHD,1);
5200  if(methodindex[ITERMODEINDEX] == ITERMODENORMAL) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITMODENORMAL,1);
5201  if(methodindex[ITERMODEINDEX] == ITERMODESTAGES) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITMODESTAGES,1);
5202  if(methodindex[ITERMODEINDEX] == ITERMODECOLD) count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITMODECOLD,1);
5203 
5204 
5205 // maybe fill du instead of these counts?
5206 // count_whocalled(ptrgeom->i,ptrgeom->j,ptrgeom->k, fakefinalstep, COUNTIMPLICITERRORS,errorabs[WHICHERROR]);
5207 // numhisterr[MAX(MIN((int)(-log10l(SMALL+errorabs[WHICHERROR])),NUMNUMHIST-1),0)]++;
5208 
5209 // unused: COUNTIMPLICITFAILED
5210 
5211  }
5212 
5213 
5214 
5215 
5216  if(PRODUCTION==0 && debugfail>=2 || PRODUCTION<=1){
5217  // counters and more detailed statistics on how the implicit solver performed
5218  // Inlcudes histogram of iterations and errors
5219  // this debug MPI stuff is very expensive
5220 
5221 
5223  //
5224  // static counter for diagnosing issues
5225  //
5227 #define NUMNUMHIST (20)
5228 
5229  static long long int numenergy=0;
5230  static long long int numentropy=0;
5231  static long long int numboth=0;
5232  static long long int numcold=0;
5233  static long long int numbad=0;
5234  static long long int numramesh=0;
5235  static long long int numrameshenergy=0;
5236  static long long int numrameshentropy=0;
5237 
5238  static long long int numqtypmhd=0;
5239  static long long int numqtyumhd=0;
5240  static long long int numqtyprad=0;
5241  static long long int numqtyurad=0;
5242  static long long int numqtyentropyumhd=0;
5243  static long long int numqtyentropypmhd=0;
5244  static long long int numitermodenormal=0;
5245  static long long int numitermodestages=0;
5246  static long long int numitermodecold=0;
5247 
5248  static long long int numimplicits=0;
5249  static long long int numexplicitsgood=0;
5250  static long long int numexplicitskindabad=0;
5251  static long long int numexplicitsbad=0;
5252  static long long int numoff1iter=0,numofiter=0;
5253  static long long int numhisterr0[NUMNUMHIST]={0}; // histogram of error for implicit solver to be reported infrequently
5254  static long long int numhisterr1[NUMNUMHIST]={0}; // histogram of error for implicit solver to be reported infrequently
5255  static long long int numhistiter[IMPMAXITERLONG+1]={0}; // histogram of error for implicit solver to be reported infrequently
5256  // static long long int numindex[NUMPRIORITERMETHODINDEX]={0};
5257 
5258  // static counter for diagnosing issues
5259  static long long int totalnumenergy=0;
5260  static long long int totalnumentropy=0;
5261  static long long int totalnumcold=0;
5262  static long long int totalnumboth=0;
5263  static long long int totalnumbad=0;
5264  static long long int totalnumramesh=0;
5265  static long long int totalnumrameshenergy=0;
5266  static long long int totalnumrameshentropy=0;
5267 
5268  static long long int totalnumqtypmhd=0;
5269  static long long int totalnumqtyumhd=0;
5270  static long long int totalnumqtyprad=0;
5271  static long long int totalnumqtyurad=0;
5272  static long long int totalnumqtyentropyumhd=0;
5273  static long long int totalnumqtyentropypmhd=0;
5274  static long long int totalnumitermodenormal=0;
5275  static long long int totalnumitermodestages=0;
5276  static long long int totalnumitermodecold=0;
5277 
5278 
5279  static long long int totalnumimplicits=0;
5280  static long long int totalnumexplicitsgood=0;
5281  static long long int totalnumexplicitskindabad=0;
5282  static long long int totalnumexplicitsbad=0;
5283  static long long int totalnumoff1iter=0,totalnumofiter=0;
5284  static long long int totalnumhisterr0[NUMNUMHIST]={0}; // histogram of error for implicit solver to be reported infrequently
5285  static long long int totalnumhisterr1[NUMNUMHIST]={0}; // histogram of error for implicit solver to be reported infrequently
5286  static long long int totalnumhistiter[IMPMAXITERLONG+1]={0}; // histogram of error for implicit solver to be reported infrequently
5287  // static long long int methodindex[NUMPRIORITERMETHODINDEX]={0};
5288 
5289 
5290  static long long int totaltryphaselistenergy[NUMPHASES];
5291  static long long int totaltryphaselistentropy[NUMPHASESENT];
5292  static long long int totaltryphaselistcold[NUMPHASESCOLD];
5293 
5294 
5296  //
5297  // Do some diagnostics and reporting. Done if ACCEPTASNOFAILURE(failreturn)==0 or not.
5298  //
5299  // KORALNOTE: If set IMPALLOWCONV to be smaller, energy solution can be then invalidated (while previously would have been used because it has no u_g issue) and go to entropy can succeed, and then appears that fewer low-energy events.
5300  // But then no FAILINFO will be reported to check why energy got high error!
5301  //
5303 
5304  // simple counters
5305  numimplicits+=usedimplicit;
5306  numexplicitsgood+=usedexplicitgood;
5307  numexplicitskindabad+=usedexplicitkindabad;
5308  numexplicitsbad+=usedexplicitbad;
5309  numofiter+=iters;
5310  numoff1iter+=f1iters;
5311  numenergy+=usedenergy;
5312  numentropy+=usedentropy;
5313  numboth+=usedboth;
5314  numcold+=usedcold;
5315  numbad+=(usedenergy==0 && usedentropy==0 && usedboth==0 && usedcold==0 && usedimplicit==1);
5316  numramesh+=gotrameshsolution;
5317  numrameshenergy+=usedrameshenergy;
5318  numrameshentropy+=usedrameshentropy;
5319 
5320  numqtypmhd += (methodindex[BASEITERMETHODINDEX] == QTYPMHD);
5321  numqtyumhd += (methodindex[BASEITERMETHODINDEX] == QTYUMHD);
5322  numqtyprad += (methodindex[BASEITERMETHODINDEX] == QTYPRAD);
5323  numqtyurad += (methodindex[BASEITERMETHODINDEX] == QTYURAD);
5324  numqtyentropyumhd += (methodindex[BASEITERMETHODINDEX] == QTYENTROPYUMHD);
5325  numqtyentropypmhd += (methodindex[BASEITERMETHODINDEX] == QTYENTROPYPMHD);
5326  numitermodenormal += (methodindex[ITERMODEINDEX] == ITERMODENORMAL);
5327  numitermodestages += (methodindex[ITERMODEINDEX] == ITERMODESTAGES);
5328  numitermodecold += (methodindex[ITERMODEINDEX] == ITERMODECOLD);
5329 
5330 
5331 
5332 
5333  // i=j=k=0 just to show infrequently
5334  if(debugfail>=2 && (ptrgeom->i==0 && ptrgeom->j==0 && ptrgeom->k==0)){
5335  dualfprintf(fail_file,"nstep=%ld numimplicits=%lld numexplicitsgood=%lld numexplicitskindabad=%lld numexplicitsbad=%lld : numenergy=%lld numentropy=%lld numboth=%lld numcold=%lld : numbad=%lld : numramesh=%lld numrameshenergy=%lld numrameshentropy=%lld : averagef1iter=%g averageiter=%g : numqtypmhd=%lld numqtyumhd=%lld numqtyprad=%lld numqtyurad=%lld numqtyentropyumhd=%lld numqtyentropypmhd=%lld numitermodenormal=%lld numitermodestages=%lld numitermodecold=%lld\n",nstep,numimplicits,numexplicitsgood,numexplicitskindabad,numexplicitsbad,numenergy,numentropy,numboth,numcold,numbad,numramesh,numrameshenergy,numrameshentropy,(FTYPE)numoff1iter/(SMALL+(FTYPE)numimplicits),(FTYPE)numofiter/(SMALL+(FTYPE)numimplicits),numqtypmhd,numqtyumhd,numqtyprad,numqtyurad,numqtyentropyumhd,numqtyentropypmhd,numitermodenormal,numitermodestages,numitermodecold);
5336  // counters for which method was *attempted* even if not used
5337  int oo;
5338  dualfprintf(fail_file,"tryenergy: ");
5339  for(oo=0;oo<NUMPHASES;oo++) dualfprintf(fail_file,"%lld ",tryphaselistenergy[oo]);
5340  dualfprintf(fail_file,"\n");
5341  dualfprintf(fail_file,"tryentropy: ");
5342  for(oo=0;oo<NUMPHASESENT;oo++) dualfprintf(fail_file,"%lld ",tryphaselistentropy[oo]);
5343  dualfprintf(fail_file,"\n");
5344  dualfprintf(fail_file,"trycold: ");
5345  for(oo=0;oo<NUMPHASESCOLD;oo++) dualfprintf(fail_file,"%lld ",tryphaselistcold[oo]);
5346  dualfprintf(fail_file,"\n");
5347  }
5348 
5349  numhisterr0[MAX(MIN((int)(-log10l(SMALL+errorabs[0])),NUMNUMHIST-1),0)]++;
5350  numhisterr1[MAX(MIN((int)(-log10l(SMALL+errorabs[1])),NUMNUMHIST-1),0)]++;
5351  numhistiter[MAX(MIN(iters,IMPMAXITERLONG),0)]++;
5352 #define HISTREPORTSTEP (DTr) //something infrequent but not too much so
5353  if(debugfail>=2 && nstep%HISTREPORTSTEP==0 && ptrgeom->i==0 && ptrgeom->j==0 && ptrgeom->k==0){
5354  int histi;
5355  for(histi=0;histi<NUMNUMHIST;histi++){
5356  dualfprintf(fail_file,"numhisterr%d=%lld %lld\n",histi,numhisterr0[histi],numhisterr1[histi]);
5357  }
5358  for(histi=0;histi<=IMPMAXITERLONG;histi++){
5359  dualfprintf(fail_file,"numhistiter%d=%lld\n",histi,numhistiter[histi]);
5360  }
5361  }
5362 
5363  // only need to get totals over cores when need to show result
5364  // i=j=k=0 just to show infrequently
5365 #define GETCOLLECTIVETOTALS ( (debugfail>=2 || PRODUCTION<=1 && nstep%HISTREPORTSTEP==0 && steppart==0 ) && (ptrgeom->i==0 && ptrgeom->j==0 && ptrgeom->k==0) )
5366 
5367  if(GETCOLLECTIVETOTALS){
5368  // over all cores
5369  if(USEMPI){
5370 #if(USEMPI)
5371  MPI_Reduce(&numimplicits, &totalnumimplicits, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5372  MPI_Reduce(&numexplicitsgood, &totalnumexplicitsgood, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5373  MPI_Reduce(&numexplicitskindabad, &totalnumexplicitskindabad, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5374  MPI_Reduce(&numexplicitsbad, &totalnumexplicitsbad, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5375  MPI_Reduce(&numoff1iter, &totalnumoff1iter, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5376  MPI_Reduce(&numofiter, &totalnumofiter, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5377  MPI_Reduce(&numenergy, &totalnumenergy, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5378  MPI_Reduce(&numentropy, &totalnumentropy, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5379  MPI_Reduce(&numboth, &totalnumboth, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5380  MPI_Reduce(&numcold, &totalnumcold, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5381  MPI_Reduce(&numbad, &totalnumbad, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5382  MPI_Reduce(&numramesh, &totalnumramesh, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5383  MPI_Reduce(&numrameshenergy, &totalnumrameshenergy, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5384  MPI_Reduce(&numrameshentropy, &totalnumrameshentropy, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5385 
5386  MPI_Reduce(&numqtypmhd, &totalnumqtypmhd, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5387  MPI_Reduce(&numqtyumhd, &totalnumqtyumhd, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5388  MPI_Reduce(&numqtyprad, &totalnumqtyprad, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5389  MPI_Reduce(&numqtyurad, &totalnumqtyurad, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5390  MPI_Reduce(&numqtyentropyumhd, &totalnumqtyentropyumhd, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5391  MPI_Reduce(&numqtyentropypmhd, &totalnumqtyentropypmhd, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5392  MPI_Reduce(&numitermodenormal, &totalnumitermodenormal, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5393  MPI_Reduce(&numitermodestages, &totalnumitermodestages, 1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5394 
5395  MPI_Reduce(numhisterr0, totalnumhisterr0, NUMNUMHIST, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5396  MPI_Reduce(numhisterr1, totalnumhisterr1, NUMNUMHIST, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5397  MPI_Reduce(numhistiter, totalnumhistiter, IMPMAXITERLONG+1, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5398 
5399  // attempt counters
5400  MPI_Reduce(tryphaselistenergy, totaltryphaselistenergy, NUMPHASES, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5401  MPI_Reduce(tryphaselistentropy, totaltryphaselistentropy, NUMPHASESENT, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5402  MPI_Reduce(tryphaselistcold, totaltryphaselistcold, NUMPHASESCOLD, MPI_LONG_LONG_INT, MPI_SUM, MPIid[0], MPI_COMM_GRMHD);
5403 #endif
5404  }
5405  else{
5406  totalnumimplicits=numimplicits;
5407  totalnumexplicitsgood=numexplicitsgood;
5408  totalnumexplicitskindabad=numexplicitskindabad;
5409  totalnumexplicitsbad=numexplicitsbad;
5410  totalnumoff1iter=numoff1iter;
5411  totalnumofiter=numofiter;
5412  totalnumenergy=numenergy;
5413  totalnumentropy=numentropy;
5414  totalnumboth=numboth;
5415  totalnumcold=numcold;
5416  totalnumbad=numbad;
5417  totalnumramesh=numramesh;
5418  totalnumrameshenergy=numrameshenergy;
5419  totalnumrameshentropy=numrameshentropy;
5420 
5421  totalnumqtypmhd=numqtypmhd;
5422  totalnumqtyumhd=numqtyumhd;
5423  totalnumqtyprad=numqtyprad;
5424  totalnumqtyurad=numqtyurad;
5425  totalnumqtyentropyumhd=numqtyentropyumhd;
5426  totalnumqtyentropypmhd=numqtyentropypmhd;
5427  totalnumitermodenormal=numitermodenormal;
5428  totalnumitermodestages=numitermodestages;
5429 
5430  int histi;
5431  for(histi=0;histi<NUMNUMHIST;histi++){
5432  totalnumhisterr0[histi]=numhisterr0[histi];
5433  totalnumhisterr1[histi]=numhisterr1[histi];
5434  }
5435  for(histi=0;histi<=IMPMAXITERLONG;histi++){
5436  totalnumhistiter[histi]=numhistiter[histi];
5437  }
5438 
5439  int oo;
5440  for(oo=0;oo<NUMPHASES;oo++){
5441  totaltryphaselistenergy[oo]=tryphaselistenergy[oo];
5442  }
5443  for(oo=0;oo<NUMPHASESENT;oo++){
5444  totaltryphaselistentropy[oo]=tryphaselistentropy[oo];
5445  }
5446  for(oo=0;oo<NUMPHASESCOLD;oo++){
5447  totaltryphaselistcold[oo]=tryphaselistcold[oo];
5448  }
5449  }
5450 
5451  if(myid==MPIid[0]){// only show result on one core that got the final result
5452  dualfprintf(fail_file,"nstep=%ld totalnumimplicits=%lld totalnumexplicitsgood=%lld totalnumexplicitskindabad=%lld totalnumexplicitsbad=%lld : totalnumenergy=%lld totalnumentropy=%lld totalnumboth=%lld totalnumcold=%lld : totalnumbad=%lld : totalnumramesh=%lld totalnumrameshenergy=%lld totalnumrameshentropy=%lld : totalaveragef1iter=%g totalaverageiter=%g : totalnumqtypmhd=%lld totalnumqtyumhd=%lld totalnumqtyprad=%lld totalnumqtyurad=%lld totalnumqtyentropyumhd=%lld totalnumqtyentropypmhd=%lld totalnumitermodenormal=%lld totalnumitermodestages=%lld totalnumitermodecold=%lld\n",nstep,totalnumimplicits,totalnumexplicitsgood,totalnumexplicitskindabad,totalnumexplicitsbad,totalnumenergy,totalnumentropy,totalnumboth,totalnumcold,totalnumbad,totalnumramesh,totalnumrameshenergy,totalnumrameshentropy,(FTYPE)totalnumoff1iter/(SMALL+(FTYPE)totalnumimplicits),(FTYPE)totalnumofiter/(SMALL+(FTYPE)totalnumimplicits),totalnumqtypmhd,totalnumqtyumhd,totalnumqtyprad,totalnumqtyurad,totalnumqtyentropyumhd,totalnumqtyentropypmhd,totalnumitermodenormal,totalnumitermodestages,totalnumitermodecold);
5453  // counters for which method was *attempted* even if not used
5454  int oo;
5455  dualfprintf(fail_file,"totaltryenergy: ");
5456  for(oo=0;oo<NUMPHASES;oo++) dualfprintf(fail_file,"%lld ",totaltryphaselistenergy[oo]);
5457  dualfprintf(fail_file,"\n");
5458  dualfprintf(fail_file,"totaltryentropy: ");
5459  for(oo=0;oo<NUMPHASESENT;oo++) dualfprintf(fail_file,"%lld ",totaltryphaselistentropy[oo]);
5460  dualfprintf(fail_file,"\n");
5461  dualfprintf(fail_file,"totaltrycold: ");
5462  for(oo=0;oo<NUMPHASESCOLD;oo++) dualfprintf(fail_file,"%lld ",totaltryphaselistcold[oo]);
5463  dualfprintf(fail_file,"\n");
5464 
5465  if(nstep%HISTREPORTSTEP==0){
5466  int histi;
5467  for(histi=0;histi<NUMNUMHIST;histi++){
5468  trifprintf("totalnumhisterr%d=%lld %lld\n",histi,totalnumhisterr0[histi],totalnumhisterr1[histi]);
5469  }
5470  for(histi=0;histi<=IMPMAXITERLONG;histi++){
5471  trifprintf("totalnumhistiter%d=%lld\n",histi,totalnumhistiter[histi]);
5472  }
5473  }
5474  }// end if myid==0
5475  }// end if getting totals
5476  }// end if ok production level to get these diags
5477 
5478 
5479 
5480  return(failfinalreturn);
5481 }
5482 
5483 
5484 
5485 
5486 
5487 
5488 
5491 static int koral_source_rad_implicit_mode(int modemethodlocal, int allowbaseitermethodswitch, int modprim, int havebackup, int didentropyalready, int *eomtype, int whichcap, int itermode, int *baseitermethod, FTYPE trueimptryconv, FTYPE trueimpokconv, FTYPE trueimpallowconv, int trueimpmaxiter, int truenumdampattempts, FTYPE fracenergy, FTYPE dissmeasure, int *radinvmod, FTYPE *pb, FTYPE *uub, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE *dUother ,FTYPE (*dUcomp)[NPR], FTYPE *errorabsreturn, FTYPE *errorabsbestexternal, int *itersreturn, int *f1itersreturn, int *nummhdinvsreturn, int *nummhdstepsreturn)
5492 {
5493  int nstrokeorig=nstroke;
5494  *nummhdinvsreturn=0;
5495  *nummhdstepsreturn=0; // global number of strokes for this core at this point, add negative so can add position later and get difference additional steps for this _mode() call
5496 
5497  // some geometry stuff to store pre-step instead of for each step.
5498  int pliter,pl;
5499  int jjdim;
5500  FTYPE dimfactU[NPR];
5501  PLOOP(pliter,pl) dimfactU[pl]=1.0; // default
5502  DLOOPA(jjdim) dimfactU[UU+jjdim]=dimfactU[URAD0+jjdim]=sqrt(fabs(ptrgeom->gcon[GIND(jjdim,jjdim)]));
5503  SLOOPA(jjdim) dimfactU[B1+jjdim-1] = 1.0/dimfactU[U1+jjdim-1];
5504 
5505 
5506  int i1,i2,i3,iv,ii,jj,kk,sc;
5507  FTYPE realdt;
5508  int gotbest,bestfailreturnf;
5509  FTYPE iJ[NPR][NPR];
5510 
5511  // store pb as might have didentropyalready=1 and then can use pborig[UU] as entropy's solution for u_g, and that can be used to create condition to avoid over-iterating with energy solver.
5512  FTYPE pborig[NPR];
5513  PLOOP(pliter,pl) pborig[pl]=pb[pl];
5514  int radinvmodorig=*radinvmod;
5515 
5516  // FTYPE trueimptryconv=IMPTRYCONV;
5517  FTYPE trueimptryconvabs=IMPTRYCONVABS;
5518  FTYPE trueimptryconvalt=IMPTRYCONVALT;
5519  FTYPE trueimpokconvabs=IMPOKCONVABS;
5520  FTYPE trueimpallowconvabs=IMPALLOWCONVABS;
5521 
5522  FTYPE trueimptryconv_orig=trueimptryconv;
5523 
5524 #if(DEBUGMAXITER)
5525  FTYPE pppreholdlist[IMPMAXITERLONG+2][NPR]={{0}}; // for debug
5526  FTYPE ppposholdlist[IMPMAXITERLONG+2][NPR]={{0}}; // for debug
5527  FTYPE f1reportlist[IMPMAXITERLONG+2][NPR]={{0}}; // for debug
5528  FTYPE f1list[IMPMAXITERLONG+2][NPR]={{0}}; // for debug
5529  FTYPE errorabsf1list[IMPMAXITERLONG+2]={0}; // for debug
5530  FTYPE errorallabsf1list[IMPMAXITERLONG+2]={0}; // for debug
5531  int realiterlist[IMPMAXITERLONG+2]; // for debug
5532  set_array(realiterlist,IMPMAXITERLONG+2,MPI_INT,-1);
5533  FTYPE jaclist[IMPMAXITERLONG+2][JACNPR][NDIM]; // for debug
5534  set_array(jaclist,(IMPMAXITERLONG+2)*NDIM*NDIM,MPI_FTYPE,BIG);
5535  int implicititerlist[IMPMAXITERLONG+2]={0}; // for debug
5536  int implicitferrlist[IMPMAXITERLONG+2]={0}; // for debug
5537 #define NUMFRACDAMP 10
5538  FTYPE fracdamplist[NUMFRACDAMP]={0};
5539 
5540 #else
5541  FTYPE errorabsf1list[IMPMAXITERLONG+2]={0}; // for tracking error
5542  FTYPE errorallabsf1list[IMPMAXITERLONG+2]={0}; // for tracking error
5543 #endif
5544 
5545  FTYPE uu0[NPR],uup[NPR],uupp[NPR],uuppp[NPR],uu[NPR],uuporig[NPR],uu0orig[NPR],bestuu[NPR];
5546  FTYPE pp0[NPR],ppp[NPR],pppp[NPR],ppppp[NPR],pp[NPR],ppporig[NPR],pp0orig[NPR],bestpp[NPR];
5547  FTYPE f1[NPR],f1norm[NPR],f1report[NPR],f3report[NPR],lowestf1[NPR],lowestf1norm[NPR],lowestf1report[NPR],lowestf3report[NPR];
5548  FTYPE f1p[NPR];
5549  FTYPE pppriorsteptype[NPR],uupriorsteptype[NPR];
5550 
5551  FTYPE radsource[NPR], deltas[NPR];
5552  extern int mathematica_report_check(int radinvmod, int failtype, long long int failnum, int gotfirstnofail, int eomtypelocal, int itermode, int baseitermethod, 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, FTYPE *CUimp, struct of_state *q, FTYPE *dUother);
5553  int mathfailtype;
5554 
5555 
5556  int eomtypelocal=*eomtype; // default choice
5557  int allowlocalfailurefixandnoreport=0; // must be 0 so implicit method knows when really failure
5558  int failreturn=0;
5559 
5560 
5561 
5562  // DEBUG VARS
5563  int showmessages=0; // by default 0, don't show any messages for inversion stuff during implicit solver, unless debugging. Assume any moment of inversion failure is corrected for now unless failure of final inversion done outside implicit solver.
5564  int showmessagesheavy=0; // very detailed for common debugging
5565  static long long int failnum=0;
5566 
5567  int doingitsomecpu=0;
5568  int doingit=0;
5569 #if(0)
5570  if(nstep==15 && steppart==0 && ptrgeom->i==6 && ptrgeom->j==8 && ptrgeom->k==0){
5571  doingitsomecpu=1;
5572  if(myid==0){ // so similar situation and grid at least
5573  dualfprintf(fail_file,"DOINGIT\n");
5574  doingit=1;
5575 
5577  // insert FAILRETURN data here.
5579 
5580  showmessages=showmessagesheavy=1;
5581  }// end on doing it core
5582  }
5583 
5584 #endif
5585 
5586 
5587 
5588 
5589 
5591  //
5592  // initialize errors
5593  //
5595  PLOOP(pliter,pl){
5596  f1[pl]=BIG;
5597  f1p[pl]=BIG;
5598  }
5599 
5600 
5602  //
5603  // setup reversion to best solution for uu in case iterations lead to worse error and reach maximum iterations.
5604  //
5606  gotbest=0;
5607  bestfailreturnf=0;
5608  PLOOP(pliter,pl){
5609  lowestf1[pl]=BIG;
5610  lowestf1norm[pl]=BIG;
5611  lowestf1report[pl]=BIG;
5612  lowestf3report[pl]=BIG;
5613  }
5614  // setup locally-used ppfirst that can pass back as pb if good solution
5615  int gotfirstnofail=0;
5616  FTYPE ppfirst[NPR];
5617 
5618 
5619 
5621  //
5622  // setup implicit iteration procedure and loops
5623  //
5625  int isexplicit=0;
5626  realdt = compute_dt(isexplicit,CUf, CUimp,dt);
5627  FTYPE fracdtuu0=1.0,fracdtG=1.0,fracuup=1.0; // initially try full realstep step
5628  FTYPE fracdtuu0p=fracdtuu0;
5629  FTYPE fracdtuu0pp=fracdtuu0p;
5630 
5631  FTYPE fracdtGp=fracdtG;
5632  FTYPE fracdtGpp=fracdtGp;
5633 
5634  int fakeitermethod=IMPMAXITERLONG;// used by normal stepping, so just make maximum
5635  struct of_method mtd;
5636  struct of_refU ru;
5637  define_method(fakeitermethod, &eomtypelocal, itermode, *baseitermethod, fracenergy, dissmeasure, &mtd);
5638  // no need to define numdims,jacs,refs, or signs yet.
5639 
5640 
5641 
5643  //
5644  // set uu0 = "initial+flux" contribution to uu
5645  //
5647  FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
5648  PLOOP(pliter,pl) uu[pl]=uu0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall);
5649 
5650 
5651 
5652 
5654  //
5655  // get default failure state from Uiin
5656  //
5658  FTYPE prtestUiin[NPR];
5659  PLOOP(pliter,pl) prtestUiin[pl]=piin[pl]; // initial guess (should be easy with piin=ppin(Uiin))
5660 
5661  //#define GETDEFAULTFAILURESTATE 1 // 1 was normal before.
5662 #define GETDEFAULTFAILURESTATE (IMPPMHDTYPE(mtd.implicititer)==0) // with new rad inversion scheme, seems to push through without issue to just let hit gamma ceiling temporarily -- even with RADPULSEPLANAR
5663  // Otherwise, takes *many* iterations, not just f1iters, to get solution. Even though that was old code state that was working, not required now.
5664 
5665 
5666  // default is to allow no failure unless iterating MHD primitives in which case a radiation failure is ok.
5667  int failreturnallowable;
5668 
5669  // no need to worry about RAD failure if not iterating rad quantities
5670  // As stated above, with new rad inversion, seems ok to temporarily hit ceiling.
5671  // With tests like RADTUBE, can't allow radiative inversion cieling else dies. While with tests like RADPULSE, fastest to converge to good solution with allowing hitting the ceiling. So mixed issue.
5672  // With RADTUBE and QTYPMHD, must also avoid rad failure if possible to avoid lack of solution, hence &&0 below.
5673  if(TREATRADINVCAPASNONFAILUREFORPMHDMETHOD && IMPMHDTYPEBASE(*baseitermethod)==1){
5674  if(IMPMHDTYPE(mtd.implicititer)) failreturnallowable=UTOPRIMGENWRAPPERRETURNFAILRAD;
5675  else failreturnallowable=UTOPRIMNOFAIL;
5676  }
5677  else{
5678  if(IMPMHDTYPE(mtd.implicititer)&&0) failreturnallowable=UTOPRIMGENWRAPPERRETURNFAILRAD;
5679  else failreturnallowable=UTOPRIMNOFAIL;
5680  }
5681 
5682  int failreturnallowableuse=failreturnallowable;
5683  int failreturnallowablefirst=-1;
5684 
5685  if(GETDEFAULTFAILURESTATE && IMPPMHDTYPE(mtd.implicititer)==0){ // No need for failure state if doing MHD iteration using primitives
5686  // KORALTODO: Instead of doing this, just keep inversion error from previously as stored in pflag. So don't reset pflag elsewhere in fixup_utoprim() for elsewhere
5687  // Need to get default failure state. Can allow such an error if having trouble with convergence (e.g. backing up too much)
5688 
5690  // be quick about checking this
5691  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
5692  newtonstats.nstroke=newtonstats.lntries=0;
5693  // set inputs for errors, maxiters, etc.
5694 #define IMPOKCONVCONSTFORDEFAULT (1E-6)
5695 #define IMPALLOWCONVCONSTFORDEFAULT (1E-4)
5696 #define IMPMAXITERFORDEFAULT (10)
5697  newtonstats.tryconv=1E-2*MAX(trueimptryconv,IMPOKCONVCONSTFORDEFAULT);
5698  newtonstats.tryconvultrarel=1E-2*MAX(trueimptryconv,IMPOKCONVCONSTFORDEFAULT);
5699  newtonstats.extra_newt_iter=1;
5700  newtonstats.extra_newt_iter_ultrarel=2;
5701  newtonstats.mintryconv=MINTRYCONVFORMHDINVERSION;//IMPALLOWCONVCONSTFORDEFAULT;
5702  newtonstats.maxiter=MIN(trueimpmaxiter,IMPMAXITERFORDEFAULT);
5703  //
5704  int finalstep = 0;
5705  int doradonly=0;
5706  eomtypelocal=*eomtype; // stick with default choice so far
5707  int checkoninversiongas;
5708  int checkoninversionrad;
5709  // don't check since slows down code and could be good enough solution if original error says ok.
5710  checkoninversiongas=checkoninversionrad=0;
5711  //
5712  failreturnallowable=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, &eomtypelocal, whichcap, EVOLVEUTOPRIM, UNOTHING, Uiin, q, ptrgeom, dissmeasure, prtestUiin, &newtonstats);
5713  *nummhdinvsreturn++;
5714  if(failreturnallowable!=UTOPRIMGENWRAPPERRETURNNOFAIL){
5715  if(showmessages && debugfail>=2) dualfprintf(fail_file,"Utoprimgen_wrapper() says that Uiin is already a problem with %d\n",failreturnallowable);
5716  }
5717  else{
5718  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"Utoprimgen_wrapper() says that Uiin is NOT a problem with %d\n",failreturnallowable);
5719  }
5720 
5721  if(failreturnallowable==UTOPRIMGENWRAPPERRETURNNOFAIL) gotfirstnofail=1;
5722  else gotfirstnofail=0;
5723  failreturnallowablefirst=failreturnallowable;
5724 
5725  // if(myid==5 && nstep==1 && steppart==0 && ptrgeom->i==19 && ptrgeom->j==15){
5726  // PLOOP(pliter,pl) dualfprintf(fail_file,"pl=%d prtestUiin=%21.15g Uiin=%21.15g\n",pl,prtestUiin[pl],Uiin[pl]);
5727  // }
5728 
5729  }
5730  else{
5731  failreturnallowablefirst=failreturnallowable;
5732  gotfirstnofail=1;//default is no failure
5733  }
5734 
5735 
5736 
5737 
5738 
5740  //
5741  // Get p(uu0) for radiative guess for pb that is used in optically thin regime when USEDUINRADUPDATE==1
5742  //
5743  // get better version of pb that agrees with uu0. This is only good for optically thin region, so best used with USEDUINRADUPDATE==1 for general optical depths.
5744  //
5745  // Getting prad(uu0_{rad parts}) is only relevant for PRAD method. All other methods overwrite the radiative pb and pp.
5746  //
5748  if((GETRADINVFROMUU0FORPB==1 && IMPPMHDTYPE(mtd.implicititer)==0) || GETRADINVFROMUU0FORPB==2 && IMPRADTYPEBASE(*baseitermethod) || GETRADINVFROMUU0FORPB==3 && (IMPRADTYPEBASE(*baseitermethod) || IMPMHDTYPEBASE(*baseitermethod) && itermode==ITERMODESTAGES)){
5749 
5750  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
5751  if(0){
5752  // initialize counters
5753  newtonstats.nstroke=newtonstats.lntries=0;
5754  // set inputs for errors, maxiters, etc.
5755  newtonstats.tryconv=trueimptryconv;
5756  newtonstats.tryconvultrarel=trueimptryconv*1E-1; // just bit smaller, not as extreme as default
5757  newtonstats.mintryconv=MINTRYCONVFORMHDINVERSION; //IMPALLOWCONV;
5758  newtonstats.maxiter=trueimpmaxiter;
5759  newtonstats.extra_newt_iter=0;
5760  newtonstats.extra_newt_iter_ultrarel=1;
5761  }
5762  else{
5764  // be quick about checking this
5765  newtonstats.nstroke=newtonstats.lntries=0;
5766  // set inputs for errors, maxiters, etc.
5767  newtonstats.tryconv=1E-2*MAX(trueimptryconv,IMPOKCONVCONSTFORDEFAULT);
5768  newtonstats.tryconvultrarel=1E-2*MAX(trueimptryconv,IMPOKCONVCONSTFORDEFAULT);
5769  newtonstats.extra_newt_iter=1;
5770  newtonstats.extra_newt_iter_ultrarel=2;
5771  newtonstats.mintryconv=MINTRYCONVFORMHDINVERSION; //IMPALLOWCONVCONSTFORDEFAULT;
5772  newtonstats.maxiter=MIN(trueimpmaxiter,IMPMAXITERFORDEFAULT);
5773  //
5774  }
5775  //
5776  int finalstep = 0;
5777  int doradonly=0;
5778  if(*baseitermethod==QTYPRAD){
5779  doradonly=1;
5780  }
5781  else doradonly=0;
5782  eomtypelocal=*eomtype; // stick with default choice so far
5783  FTYPE prtest[NPR];
5784  int whichcapnew=CAPTYPEFIX2; // so Erf doesn't drop out for guess.
5785  int checkoninversiongas;
5786  int checkoninversionrad;
5787  // don't check since slows down code and could be good enough solution if original error says ok.
5788  checkoninversiongas=checkoninversionrad=0;
5789  //
5790  PLOOP(pliter,pl) prtest[pl]=pb[pl];
5791  failreturnallowable=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, &eomtypelocal, whichcapnew, EVOLVEUTOPRIM, UNOTHING, uu0, q, ptrgeom, dissmeasure, prtest, &newtonstats);
5792  if(doradonly==0) *nummhdinvsreturn++;
5793  if(*baseitermethod==QTYPRAD && (1||failreturnallowable==UTOPRIMGENWRAPPERRETURNNOFAIL)){ // 1|| so assigns if failed or not, because with CAPTYEPFIX2 won't give dropped-out answer.
5794  PLOOP(pliter,pl) if(RADFULLPL(pl)) pb[pl]=prtest[pl];
5795  }
5796  else if(*baseitermethod==QTYPMHD && (failreturnallowable==UTOPRIMGENWRAPPERRETURNNOFAIL)){
5797  // if not iterating radiation primitives, then these rad primitives will be overwritten by first f_implicit() call, so avoid...
5798  PLOOP(pliter,pl) if(RADFULLPL(pl)) pb[pl]=prtest[pl];
5799  }
5800  else{
5801  // then just leave pb as pb.
5802  }
5803  }
5804 
5805 
5806 
5807 
5808 
5810  //
5811  // see if uu0->p possible and desired. Or just assign pp,pb,uu in terms of piin,Uiin,uu0 (based possibly upon optical depth).
5812  //
5814  FTYPE prtestUU0[NPR];
5815  PLOOP(pliter,pl) prtestUU0[pl]=pb[pl]; // initial guess
5816 
5817  // KORALTODO: Need to check if UFSET with no dUother fails. How it fails, must allow since can do nothing better. This avoids excessive attempts to get good solution without that failure! Should speed-up things. But what about error recovery? If goes from CASE to no case!
5818  if(USEDUINRADUPDATE==3){
5819  // uu0 will hold original vector of conserved
5820  // here original means U[before fluxes, geometry, etc.] + dU[due to fluxes, geometry, etc. already applied and included in dUother]
5821  // This is required for stiff source term so immediately have balance between fluxes+geometry+radiation. Otherwise, radiation diffuses.
5822  // I'm guessing that even though one uses RK2 or RK3, the first step generates large radiative velocities without any balanced source term since U isn't updated yet.  One would hope RK2 would recover on the final substep, but it doesn't!  In RK2, upon the final substep, that velocity is present for the radiation source term.  But it's also present for the fluxes!  That is, if there were no flux update on the final substep, then the source would have balanced the previous flux, but yet another flux is done, so there can be no balance.  This leads to a run-away velocity that would be similar to the \tau\sim 1 case.
5823  // NOTE: If this gives radiation or mhd failure, then less likely that will be actual solution since not even original uu0 has inversion.
5824  // Note that "q" isn't used in this function or used in function call, so don't have to update it here.
5825 
5826  // Need to get default failure state. Can allow such an error if having trouble with convergence (e.g. backing up too much)
5827  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
5828  if(0){
5829  // initialize counters
5830  newtonstats.nstroke=newtonstats.lntries=0;
5831  }
5832  else{
5834  // be quick about checking this
5835  newtonstats.nstroke=newtonstats.lntries=0;
5836  // set inputs for errors, maxiters, etc.
5837  newtonstats.tryconv=1E-2*MAX(trueimptryconv,IMPOKCONVCONSTFORDEFAULT);
5838  newtonstats.tryconvultrarel=1E-2*MAX(trueimptryconv,IMPOKCONVCONSTFORDEFAULT);
5839  newtonstats.extra_newt_iter=1;
5840  newtonstats.extra_newt_iter_ultrarel=2;
5841  newtonstats.mintryconv=MINTRYCONVFORMHDINVERSION; //IMPALLOWCONVCONSTFORDEFAULT;
5842  newtonstats.maxiter=MIN(trueimpmaxiter,IMPMAXITERFORDEFAULT);
5843  }
5844  //
5845  int failreturninversion;
5846  int finalstep = 0;
5847  int doradonly=0;
5848  int checkoninversiongas;
5849  int checkoninversionrad;
5850  // don't check since slows down code and could be good enough solution if original error says ok.
5851  checkoninversiongas=checkoninversionrad=0;
5852  //
5853  eomtypelocal=*eomtype; // stick with default choice so far
5854  failreturninversion=Utoprimgen_failwrapper(doradonly,radinvmod,showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep, &eomtypelocal, whichcap, EVOLVEUTOPRIM, UNOTHING, uu0, q, ptrgeom, dissmeasure, prtestUU0, &newtonstats);
5855  *nummhdinvsreturn++;
5856 
5857 
5858  // get pp0(uu0) so uu,uu0 properly associated with pp,pp0
5859  // set first pp that is p(uu0), assuming that can do inversion
5860  PLOOP(pliter,pl) ppfirst[pl]=pp[pl]=pp0[pl]=prtestUU0[pl];
5861 
5862  }
5863  else if(USEDUINRADUPDATE==2){
5864  // normal behavior, where uu0 has no known primitive inversion yet.
5865  // if entropy got solution and then energy is being done here, then pb is good entropy guess.
5866  PLOOP(pliter,pl){
5867  uu[pl] = uu0[pl];
5868  ppfirst[pl] = pp[pl] = pp0[pl] = pb[pl];
5869  }
5870  }
5871  else if(USEDUINRADUPDATE==1){
5872 
5873 
5874  // use tau as guess for which guess is best
5875  FTYPE tautot[NDIM]={0.0},tautotmax=0.0;
5876  calc_tautot(pb, ptrgeom, q, tautot, &tautotmax);
5877 
5878  // allow tolerance to be higher if optically thin enough
5879  if(tautotmax<TAUTOTMAXHIGHERTOL){
5880  trueimptryconv=IMPTRYCONV_TAUTOTMAXHIGHERTOL;
5881  // FTYPE trueimptryconv=IMPTRYCONV;
5882  trueimptryconvabs=IMPTRYCONVABS;
5883  trueimptryconvalt=IMPTRYCONVALT;
5884  }
5885  else{ // back to orig
5886  trueimptryconv=trueimptryconv_orig;
5887  // FTYPE trueimptryconv=IMPTRYCONV;
5888  trueimptryconvabs=IMPTRYCONVABS;
5889  trueimptryconvalt=IMPTRYCONVALT;
5890  }
5891 
5892  // iterated, so keep as initial (i.e. previous full solution, not just initial+flux)
5893  PLOOP(pliter,pl){
5894  if(tautotmax>=TAUSWITCHPBVSPIIN){
5895  uu[pl] = Uiin[pl]; // assume somewhat static and Uiin is best guess
5896  ppfirst[pl] = pp[pl] = pp0[pl] = piin[pl];
5897  }
5898  else{
5899  uu[pl] = uu0[pl]; // assume dynamic and should use full uu0 to avoid pushing any errors into other fluid component.
5900  ppfirst[pl] = pp[pl] = pp0[pl] = pb[pl];
5901  }
5902  }
5903  // non-iterated, so keep as initial+flux (since all there is)
5904  PLOOP(pliter,pl){
5905  if(!(pl>=UU && pl<=U3 || RADPL(pl) || pl==ENTROPY)){
5906  uu[pl] = uu0[pl];
5907  ppfirst[pl] = pp[pl] = pp0[pl] = pb[pl];
5908  }
5909  }
5910 
5911  }
5912  else if(USEDUINRADUPDATE==0){
5913  // bad choice for non-iterated quantities, like uu[RHO] should be uu0[RHO]
5914  PLOOP(pliter,pl){
5915  uu[pl] = Uiin[pl];
5916  ppfirst[pl] = pp[pl] = pp0[pl] = piin[pl];
5917  }
5918  }
5919  else{
5920  // then (not recommended) just using Uiin as uu0 . KORALNOTE: uu0 reset later, but intermediates would use this uu0.
5921  PLOOP(pliter,pl){
5922  uu[pl] = uu0[pl] = Uiin[pl];
5923  ppfirst[pl] = pp[pl] = pp0[pl] = piin[pl];
5924  }
5925  }
5926 
5927 
5929  // if error small enough and no fixups used with the radative inversion, override guess to use previous solution as the new guess
5930  if(errorabsreturn[WHICHERROR]<TRYHARDERFEEDGUESSTOL && RADINVBAD(radinvmodorig)==0){
5931  PLOOP(pliter,pl){
5932  pp[pl] = pp0[pl] = ppfirst[pl] = pb[pl]; // not just F(pb) anymore, holds better guess
5933  uu[pl] = uub[pl]; // not just Uiin or uu0 anymore, holds better guess
5934  }
5935  }
5936  }
5937 
5938 
5940  //
5941  // Fix u_g so entropy not smaller than guess
5942  // Only do this if u_g is just guess and is being solved for.
5943  // When eomtype==EOMCOLDGRMHD, then u_g is static so shouldn't modify as if was guess.
5944  //
5946 
5947  if(*eomtype!=EOMCOLDGRMHD && IMPMHDTYPE(mtd.implicititer)==1 && modprim==1){
5948  if(ENTROPYFIXGUESS){
5949  entropyfixguess(q, ptrgeom, uu0, pp);
5950  // piin is sometimes even a bit higher, and want to start high, and helps to avoid lack of convergence issue.
5951  pp[UU]=MAX(pp[UU],piin[UU]);
5952  }
5953 
5954  if(modprim==1){
5955  pp[UU]=10.0*MAX(pp[UU],piin[UU]); // raise u_g a bit.
5956  }
5957  }
5958 
5959 
5960 
5961 
5962 
5963 
5965  //
5966  // SETUP Damping loop
5967  //
5969 
5970  FTYPE ppdampbackup[NPR],uudampbackup[NPR],uu0dampbackup[NPR];
5971  // backup those things that below can change, yet we want to start fresh each damp attempt (except best and backup stuff values and errors)
5972  PLOOP(pliter,pl){
5973  ppdampbackup[pl]=pp[pl];
5974  uudampbackup[pl]=uu[pl];
5975  uu0dampbackup[pl]=uu0[pl];
5976  }
5977  // backups and bests
5978  int gotbackup=0;
5979  int totaliters=0;
5980  int iter=0;
5981  int debugiter=0;
5982  int debugiteratteempts[NUMDAMPATTEMPTS];
5983  int momiters=0,energyiters=0,fulliters=0;
5984  FTYPE errorabsf1[NUMERRORTYPES];
5985  set_array(errorabsf1,NUMERRORTYPES,MPI_FTYPE,BIG);
5986  FTYPE suberrorabsf1=BIG;
5987  FTYPE errorabsf3=BIG;
5988  FTYPE suberrorabsf3=BIG;
5989  // things that can happen that then no matter what other conditions, avoid damping or other attempts.
5990  int lowitererror=0;
5991  int earlylowerror=0;
5992 
5993  // best is over all damps as well
5994  FTYPE errorabsbest[NUMERRORTYPES];
5995  set_array(errorabsbest,NUMERRORTYPES,MPI_FTYPE,BIG);
5996  int failreturnbest=FAILRETURNGENERAL;
5997  int radinvmodbest=UTOPRIMRADFAILBAD1;
5998 
5999  FTYPE tautotmaxreturn;
6000 
6001 
6002  int f1iterstart=0;
6003  int explicitattempt;
6004  for(explicitattempt=0;explicitattempt<=DONONEXPLICITIFFAILS;explicitattempt++){
6005 
6006  gotbackup=0;
6007  iter=0;
6008  debugiter=0;
6009  set_array(errorabsf1,NUMERRORTYPES,MPI_FTYPE,BIG);
6010  suberrorabsf1=BIG;
6011  errorabsf3=BIG;
6012  suberrorabsf3=BIG;
6013 
6014  if(explicitattempt>0 && (lowitererror || earlylowerror || errorabsf1[WHICHERROR]<IMPTRYDAMPCONV && ACCEPTASNOFAILURE(failreturn) || failreturn==FAILRETURNMODESWITCH) ){ // try damping if any bad failure or not desired tolerance when damping
6015  break;
6016  }
6017  if(explicitattempt==1){
6018  f1iterstart=1;
6019  }
6020  else f1iterstart=0;
6021  PLOOP(pliter,pl){
6022  pp[pl]=ppdampbackup[pl];
6023  uu[pl]=uudampbackup[pl];
6024  uu0[pl]=uu0dampbackup[pl];
6025  }
6026 
6027 
6028 
6029 
6031  //
6032  // THE DAMP LOOP ITSELF
6033  //
6035  int dampattempt;
6036  for(dampattempt=0;dampattempt<truenumdampattempts;dampattempt++){
6037  FTYPE DAMPFACTOR0;
6038  // dampattempt>0 refers to any attempt beyond the very first. Uses iter from end of region inside this loop.
6039  if(dampattempt>0 && (lowitererror || earlylowerror || errorabsf1[WHICHERROR]<IMPTRYDAMPCONV && ACCEPTASNOFAILURE(failreturn) || failreturn==FAILRETURNMODESWITCH) ){ // try damping if any bad failure or not desired tolerance when damping
6040  if(dampattempt>=2 && failreturn!=FAILRETURNMODESWITCH){ // dampattempt>=2 refers to attempts with at least 1 damp attempt
6041  if(debugfail>=2) dualfprintf(fail_file,"Damping worked to reach desired tolerance: errorabsf1=%g errorallabsf1=%g (IMPTRYDAMPCONV=%g), so should have lower error: dampattempt=%d iter=%d ijk=%d %d %d\n",errorabsf1[0],errorabsf1[1],IMPTRYDAMPCONV,dampattempt,iter,ptrgeom->i,ptrgeom->j,ptrgeom->k);
6042  }
6043  break; // if didn't hit problem, so no need to damp since got tolerance requested or returned because will just switch to another scheme.
6044  }
6045  else{
6046  // control factor by which step Newton's method.
6047  if(dampattempt==0) DAMPFACTOR0=1.0;
6048  else DAMPFACTOR0=1.0/pow(2.0,(FTYPE)(dampattempt));
6049 
6050  if(dampattempt>0) if(debugfail>=2) dualfprintf(fail_file,"Trying dampattempt=%d DAMPFACTOR0=%g failreturn=%d errorabsf1=%g errorallabsf1=%g iter=%d ijk=%d %d %d\n",dampattempt,DAMPFACTOR0,failreturn,errorabsf1[0],errorabsf1[1],iter,ptrgeom->i,ptrgeom->j,ptrgeom->k);
6051 
6052  // start fresh
6053  iter=debugiter=0;
6054  failreturn=FAILRETURNNOFAIL; // default is no failure
6055  mathfailtype=-1; // indicates not set
6056  {
6057  // PLOOP(pliter,pl) uu0[pl]=uu0dampbackup[pl];
6058  }
6059  if(errorabsf1[WHICHERROR]<TRYHARDERFEEDGUESSTOL){
6060  // then keep pp and uu as better starting point
6061  }
6062  else{
6063  PLOOP(pliter,pl){
6064  pp[pl]=ppdampbackup[pl];
6065  uu[pl]=uudampbackup[pl];
6066  uu0[pl]=uu0dampbackup[pl];
6067  }
6068  }
6069 
6070  }
6071 
6072 
6073 
6074 
6075 
6077  //
6078  // SETUP IMPLICIT ITERATIONS
6079  //
6081  int f1iter;
6082  int checkconv,changeotherdt=1;
6083  FTYPE impepsjac=IMPEPSLARGE; // default
6084  FTYPE errorabspf1[NUMPRIORERRORS];
6085  set_array(errorabspf1,NUMPRIORERRORS,MPI_FTYPE,BIG);
6086  FTYPE errorabspf3=BIG;
6087 
6088  // initialize previous 'good inversion' based uu's
6089  PLOOP(pliter,pl){
6090  uupriorsteptype[pl]=uuppp[pl]=uupp[pl]=uuporig[pl]=uup[pl]=uu0orig[pl]=uu[pl];
6091  pppriorsteptype[pl]=ppppp[pl]=pppp[pl]=ppporig[pl]=ppp[pl]=pp0orig[pl]=pp[pl];
6092  }
6093 
6094 
6095  // setup debug so can see starting guess
6096 #if(DEBUGMAXITER)
6097  int iterlist=0;
6098  if(dampattempt==0){
6099  PLOOP(pliter,pl) pppreholdlist[iterlist][pl]=pp[pl];
6100  PLOOP(pliter,pl) ppposholdlist[iterlist][pl]=pp[pl];
6101  if(DEBUGMAXITERVELOCITY==1){
6102  SLOOPA(jj){
6103  pppreholdlist[iterlist][U1+jj-1]=q->ucon[jj];
6104  pppreholdlist[iterlist][URAD1+jj-1]=q->uradcon[jj];
6105  ppposholdlist[iterlist][U1+jj-1]=q->ucon[jj];
6106  ppposholdlist[iterlist][URAD1+jj-1]=q->uradcon[jj];
6107  }
6108  }
6109  PLOOP(pliter,pl) f1reportlist[iterlist][pl]=BIG;
6110  PLOOP(pliter,pl) f1list[iterlist][pl]=BIG;
6111  realiterlist[iterlist]=-1;
6112  DLOOP(jj,kk) jaclist[iterlist][jj][kk]=BIG;
6113  implicititerlist[iterlist]=-1;
6114  implicitferrlist[iterlist]=-1;
6115  fracdamplist[0]=fracdtuu0;
6116  fracdamplist[1]=fracdtG;
6117  fracdamplist[2]=0;
6118  }
6119  errorabsf1list[iterlist]=BIG;
6120  errorallabsf1list[iterlist]=BIG;
6121 #else
6122  {
6123  int iterlist=0;
6124  errorabsf1list[iterlist]=BIG;
6125  errorallabsf1list[iterlist]=BIG;
6126  }
6127 #endif
6128 
6129  // DEBUG:
6130  errorabsreturn[0]=errorabsreturn[1]=BIG;
6131 
6132  // whether holding as positive and outher counts
6133  // or things that happen that mean need to break out of this attempt, but not break out of damping loop.
6134  int holdingaspositive=0,iterhold=0;
6135  int countholdpositive=0;
6136  int countugnegative=0;
6137  int countbadenergy=0;
6138  int counterrorrose=0;
6139  int priorerrorscount=0;
6140  int canbreak=0;
6141  int notfinite=0;
6142  int convreturnf3limit=0;
6143  int notholding=1;
6144  FTYPE DAMPFACTOR;
6145  int numjumpchecks=0;
6146 
6148  //
6149  // IMPLICIT LOOP ITSELF
6150  //
6152 
6153  do{
6154  debugiter++; // never skips, goes every step
6155  // dualfprintf(fail_file,"iter=%d debugiter=%d\n",iter,debugiter);
6156  debugiteratteempts[dampattempt]=debugiter;
6157  iter++; // below might skip some iter, used to control which equations used
6158 
6159 
6160 
6161  // setup method and signs
6162  define_method(iter, &eomtypelocal, itermode, *baseitermethod, fracenergy, dissmeasure, &mtd);
6163  get_refUs(&mtd, &ru);
6164 
6165 
6166  if(iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){
6167  momiters++;
6168  }
6169  if(iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){
6170  energyiters++;
6171  }
6172  if(iter>=mtd.BEGINFULLSTEPS && iter<=mtd.ENDFULLSTEPS){
6173  fulliters++;
6174  }
6175 
6176 
6177 
6178 
6180  //
6181  // things to reset each iteration start for any steps
6182  //
6184  canbreak=0; // reset each start of iteration
6185  convreturnf3limit=0;
6186  notholding=1; // default is no hold
6187  earlylowerror=0; // reset each iteration
6188  lowitererror=0;
6189 
6190  if(iter>10){ // KORALTODO: improve upon this later. Only matters if not doing PMHD method
6191  // assume trying hard and failing to work, then allow CASE radiation errors
6192  failreturnallowable=failreturnallowableuse=UTOPRIMGENWRAPPERRETURNFAILRAD;
6193  }
6194 
6195  if(CHANGEDAMPFACTOR==1){
6196  if(trueimpmaxiter==IMPMAXITERQUICK && iter>IMPMAXITERQUICK/2){
6197  DAMPFACTOR=0.5*DAMPFACTOR0;
6198  }
6199  else if(trueimpmaxiter==IMPMAXITERLONG && iter>MIN(IMPMAXITERLONG/2,20)){
6200  DAMPFACTOR=0.5*DAMPFACTOR0;
6201  }
6202  else DAMPFACTOR=DAMPFACTOR0;
6203  }
6204  else if(CHANGEDAMPFACTOR==2){
6205  if(itermode==ITERMODESTAGES && iter==mtd.BEGINMOMSTEPS) DAMPFACTOR=0.5*DAMPFACTOR0; else DAMPFACTOR=DAMPFACTOR0;
6206  if(itermode==ITERMODESTAGES && iter==mtd.BEGINENERGYSTEPS) DAMPFACTOR=0.5*DAMPFACTOR0; else DAMPFACTOR=DAMPFACTOR0;
6207  if(itermode==ITERMODESTAGES && iter==mtd.BEGINFULLSTEPS) DAMPFACTOR=0.25*DAMPFACTOR0; else DAMPFACTOR=DAMPFACTOR0; // 0.25 to be very careful since can change energy too much when suddenly turning back on momentum
6208  }
6209  else DAMPFACTOR=DAMPFACTOR0;
6210 
6211 
6212 
6214  //
6215  // vector of conserved, primitives, and fractions of steps used at the previous few iterations
6216  //
6218  PLOOP(pliter,pl){
6219  uuppp[pl]=uupp[pl]; // uuppp...
6220  uupp[pl]=uup[pl]; // uupp will have solution for inversion: P(uupp)
6221  uup[pl]=uu[pl]; // uup will not necessarily have P(uup) because uu used Newton step.
6222  uuporig[pl]=uu[pl];
6223 
6224  ppppp[pl]=pppp[pl]; // ppppp will have knowledge of 2 prior errorabsf1's
6225  pppp[pl]=ppp[pl]; // pppp will have solution for inversion
6226  ppp[pl]=pp[pl]; // ppp will not necessarily have solution because pp used Newton step.
6227  ppporig[pl]=pp[pl];
6228  }
6229 
6230  fracdtuu0pp=fracdtuu0p; // fracdtuu0 used when computing previous f1 and f2's
6231  fracdtuu0p=fracdtuu0; // fracdtuu0 used when computing previous f1 and f2's
6232 
6233  fracdtGpp=fracdtGp; // fracdtG used when computing previous f1 and f2's
6234  fracdtGp=fracdtG; // fracdtG used when computing previous f1 and f2's
6235 
6236  errorabspf3=errorabsf3;
6237 
6238 
6240  //
6241  // reset at start of new use of equations
6242  //
6244  int itererror;
6245  if(iter==mtd.BEGINMOMSTEPS || iter==mtd.BEGINENERGYSTEPS || iter==mtd.BEGINFULLSTEPS){
6246  iterhold=0;
6247  countbadenergy=0;
6248  counterrorrose=0;
6249  priorerrorscount=0;
6250  holdingaspositive=0;
6251  countholdpositive=0;
6252  countugnegative=0;
6253  for(itererror=0;itererror<NUMPRIORERRORS;itererror++) errorabspf1[itererror]=BIG;
6254  // store uu,pp before modified using new step
6255  PLOOP(pliter,pl){
6256  uupriorsteptype[pl]=uu[pl];
6257  pppriorsteptype[pl]=pp[pl];
6258  }
6259  }
6260  else if(iter>1){
6261  for(itererror=MIN(priorerrorscount,NUMPRIORERRORS)-1;itererror>=1;itererror--) errorabspf1[itererror]=errorabspf1[itererror-1]; // shift to higher
6262  errorabspf1[0]=suberrorabsf1; // only for equations that are currently iterating.
6263  }
6264  // store previous f1 values
6265  PLOOP(pliter,pl) f1p[pl]=f1[pl];
6266 
6267 
6268 
6269 
6270  // KORALTODO: Once use certain uu0 value and succeed in getting f1, not enough. But if take a step and *then* good f1, then know that original U was good choice and can restart from that point instead of backing up uu0 again.
6271  // KORALTODO: Look at whether bounding error by sign as in bisection (only true in 1D!!), and if approaching 0 slowly enough and still hit CASE, then must be real CASE not a stepping issue.
6272  // KORALTODO: Getting f1 is just about f1(U) as far as radiation is concerned. So as far as CASE issues, getting f1(U) means we are good with that U and we can certainly stick with the used uu0.
6273 
6274 
6275 
6276 
6278  //
6279  // get error function (f1) and inversion (uu->pp) using uu
6280  //
6282  int failreturnferr;
6283  int convreturnf1;
6284  for(f1iter=f1iterstart;f1iter<MAXF1TRIES;f1iter++){
6285 
6286  // dualfprintf(fail_file,"iter=%d debugiter=%d f1iter=%d\n",iter,debugiter,f1iter);
6287 
6288 
6289  int whichcall=FIMPLICITCALLTYPEF1;
6290  eomtypelocal=*eomtype; // re-chose default each time. If this reduces to a new eomtype, then Jacobian will stick with that for consistency!
6291  int goexplicit;
6292  int dimtypef=DIMTYPEFCONS;
6293 
6294  // get original baseitermethod
6295  int baseitermethodorig=*baseitermethod;
6296  // use ppppp and uuppp as backup since one previous step is often off alot even if not already hitting point at which one should change baseitermethod
6297  failreturnferr=f_implicit(allowbaseitermethodswitch, iter, f1iter, failreturnallowableuse, whichcall, impepsjac, showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, baseitermethod, fracenergy, dissmeasure, radinvmod, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, ppppp, pp, piin, uuppp, Uiin, uu0, uu, fracdtG*realdt, ptrgeom, q, f1, f1norm, f1report, &goexplicit, &errorabsf1[0], &errorabsf1[1], WHICHERROR, &convreturnf1, nummhdinvsreturn, &tautotmaxreturn, &mtd, &ru); // modifies uu and pp, f1poret, goexplicit, errorabsf1[0,1], convreturnf1
6298 
6299 
6300  // see if 4-force negligible
6301  if(goexplicit){
6302  // immediate return.
6303  return(-1);
6304  }
6305 
6306 
6307  // allow tolerance to be higher if optically thin enough, track for each iteration in case changes!
6308  if(tautotmaxreturn<TAUTOTMAXHIGHERTOL){
6309  trueimptryconv=IMPTRYCONV_TAUTOTMAXHIGHERTOL;
6310  // FTYPE trueimptryconv=IMPTRYCONV;
6311  trueimptryconvabs=IMPTRYCONVABS;
6312  trueimptryconvalt=IMPTRYCONVALT;
6313  }
6314  else{
6315  trueimptryconv=trueimptryconv_orig;
6316  // FTYPE trueimptryconv=IMPTRYCONV;
6317  trueimptryconvabs=IMPTRYCONVABS;
6318  trueimptryconvalt=IMPTRYCONVALT;
6319  }
6320 
6321 
6322  // if baseitermethod changed, then need to deal with fracdtuu0 that may have different properties. So while we don't necessarily go back too far on pp,uu, we need to pretend starting over with how we deal with uu0.
6323  if(*baseitermethod!=baseitermethodorig) iter=1;
6324 
6325 
6326 #if(MODEMETHOD==MODEENERGY ||MODEMETHOD==MODEENTROPY ||MODEMETHOD==MODESWITCH)
6327  // setup method and signs in case changed baseitermethod
6328  define_method(iter, &eomtypelocal, itermode, *baseitermethod, fracenergy, dissmeasure, &mtd);
6329  get_refUs(&mtd, &ru);
6330 #endif
6331 
6332 
6333 
6334  // f1 error calculation updated non-iterated pp or uu, so store. Ok to re-store iterated uu and pp as well
6335  // KORALTODO: This might mess up when f1 backs-up uu and pp
6336  PLOOP(pliter,pl){
6337  uup[pl]=uu[pl];
6338  ppp[pl]=pp[pl];
6339  }
6340 
6341 
6342 #if(0)
6343  if(pp[PRAD0]<10.0*ERADLIMIT){
6344  // try smaller tolerance
6345  trueimptryconv=10.0*NUMEPSILON;
6346  trueimptryconvabs=((FTYPE)(NDIM+2)*trueimptryconv);
6347  trueimptryconvalt=(MAX(1E-8,trueimptryconvabs));
6348  }
6349 #endif
6350 
6351 
6352  if(failreturnferr){
6353 
6354  // if(debugfail>=2) dualfprintf(fail_file,"Failed f1: %d\n",failreturnferr);
6355 
6356 #define BACKUPRELEASEFAIL0 (1E-4)
6357 #define BACKUPRELEASEFAIL1 (1E-6)
6358 #define BACKUPRELEASEFAIL2 (1E-7)
6359 #define MAXF1ITERRADTRY (10) // number of iterations after which to release and allow radiation to "fail"
6360 
6361  // if backing up alot, then allow same failure as original Uiin in hopes that can recover that way (otherwise would have hoped would recover via flux update to Uiin)
6362  if(fracdtuu0<BACKUPRELEASEFAIL0){
6363  failreturnallowableuse=failreturnallowable;
6364  }
6365  if(fracdtuu0<BACKUPRELEASEFAIL1 || f1iter>=MAXF1ITERRADTRY){
6366  failreturnallowableuse=UTOPRIMGENWRAPPERRETURNFAILRAD;
6367  }
6368 
6369 
6370  if(iter==1){
6371  // if initial uu failed, then should take smaller jump from Uiin->uu until settled between fluid and radiation.
6372  // If here, know original Uiin is good, so take baby steps in case uu needs heavy raditive changes.
6373  // if f1 fails, try going back to Uiin a bit
6374  fracdtuu0*=RADDAMPDELTA; // DAMP Uiin->uu0 step that may be too large and generated too large G
6375  fracdtuu0=MIN(1.0,fracdtuu0);
6376 
6377  // if(fracdtuu0<BACKUPRELEASEFAIL2) fracdtuu0=0.0; // just stop trying to start with some uu0 and revert to Uiin
6378 
6379  // modifies uup (ppp) and uu (pp) as if starting over, and then another call to f_implicit(f1) will change uu by generally smaller amount.
6380  PLOOP(pliter,pl){
6381  uup[pl]=uu[pl]=uu0[pl];
6382  ppp[pl]=pp[pl]=pp0[pl];
6383  }
6384  }
6385  else{
6386  // if here, then assume prior uup was good in sense that no failures like P(uup) is good inversion. And uu=uup before f_implicit(f1) is called.
6387  // No, not necessarily true, because uu updated with some-sized Newton step without checking if inversion is good for that uu.
6388  // So need to damp between original uup and uupp . This essentially damps Newton step now that have knowledge the Newton step was too large as based upon P(U) failure.
6389 
6390  // Avoid G-damping because not needed so far. If added, competes in non-trivial way with fracuup damping that's required separately for large forces in some problems beyond iter=1 (e.g. NTUBE=31).
6391  // fracdtG*=RADDAMPDELTA; // DAMP give only fraction of 4-force to let uu to catch-up
6392  // fracdtG=0.5; // DAMP give only fraction of 4-force to let uu to catch-up
6393 
6394  fracuup*=RADDAMPDELTA; // DAMP in case Newton step is too large after iter>1 and stuck with certain uu from Newton step that gets stored in uup above.
6395 
6396  PLOOP(pliter,pl) uu[pl]=(1.0-fracuup)*uupp[pl] + fracuup*uuporig[pl];
6397  // PLOOP(pliter,pl) uu[pl]=(1.0-fracuup)*uupp[pl] + fracuup*uup[pl];
6398  PLOOP(pliter,pl) uup[pl]=uu[pl]; // store new version of prior Newton step
6399 
6400  PLOOP(pliter,pl) pp[pl]=(1.0-fracuup)*pppp[pl] + fracuup*ppporig[pl];
6401  // PLOOP(pliter,pl) pp[pl]=(1.0-fracuup)*pppp[pl] + fracuup*ppp[pl];
6402  PLOOP(pliter,pl) ppp[pl]=pp[pl]; // store new version of prior Newton step
6403 
6404  // get interpolated fracdtuu0 so using fracdtuu0 that was used with the corresponding uu
6405  fracdtuu0=(1.0-fracuup)*fracdtuu0pp + fracuup*fracdtuu0p;
6406  // same for fracdtG
6407  fracdtG=(1.0-fracuup)*fracdtGpp + fracuup*fracdtGp;
6408 
6409  }
6410 
6411 
6412  // get uu0 (which may be changing)
6413  // FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
6414  PLOOP(pliter,pl) uu0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall);
6415  {
6416  FTYPE uuiterback[NPR];
6417  PLOOP(pliter,pl) uuiterback[pl] = uu[pl]; // hold actual iterated quantities
6418  PLOOP(pliter,pl) uu[pl] = uu0[pl]; // "iterate" non-iterated quantities
6419  JACLOOP(ii,ru.startjac,ru.endjac) uu[ru.irefU[ii]] = uuiterback[ru.irefU[ii]]; // overwrite with actual previous step for iterated quantities
6420  }
6421  // KORALNOTE: pp0 not used, setting uu0 above fixes error function where only uu0 is needed.
6422 
6423 
6424 
6425  // keep below so can count inversion failures against retry successes in the failure file.
6426  if(showmessages && debugfail>=2) dualfprintf(fail_file,"f_implicit for f1 failed: iter=%d Backing-up both uu0 and G.: f1iter=%d fracdtuu0=%g fracdtG=%g fracuup=%g\n",iter,f1iter,fracdtuu0,fracdtG,fracuup);
6427  if(showmessagesheavy) PLOOP(pliter,pl) dualfprintf(fail_file,"pl=%d Ui=%26.20g uu0=%26.20g uu0orig=%26.20g uu=%26.20g uup=%26.20g dUother=%26.20g\n",pl,Uiin[pl],uu0[pl],uu0orig[pl],uu[pl],uup[pl],dUother[pl]);
6428  }// end if failed inversion in f_implicit()
6429  else{
6430  // then success, so was able to do inversion P(U) with change in radiation on fluid: P(uu[fluid] = uu0[fluid] - (uu[rad]-uu0[rad]))
6431  // This doesn't necessarily mean could do P(uu0) except for iter=1.
6432  // Corresponds to success for a certain P(uu0,uu) pair.
6433  if(showmessagesheavy) PLOOP(pliter,pl) dualfprintf(fail_file,"SUCCESS: pl=%d Ui=%26.20g uu0=%26.20g uu0orig=%26.20g uu=%26.20g uup=%26.20g dUother=%26.20g: pp(pnew)=%g : fracdtuu0=%g fracdtG=%g fracuup=%g\n",pl,Uiin[pl],uu0[pl],uu0orig[pl],uu[pl],uup[pl],dUother[pl],pp[pl],fracdtuu0,fracdtG,fracuup);
6434  break;
6435  }
6436 
6437  // if during f1iter-ations u_g or rho is negative, switch to entropy
6438 #define F1ITERSWITCHONNEG 20
6439  if(havebackup){
6440  if(f1iter>F1ITERSWITCHONNEG && (pp[RHO]<0 || pp[UU]<0)){
6441  failreturn=FAILRETURNMODESWITCH; mathfailtype=70;
6442  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"Switched modes during f1iter=%d : rho=%21.15g ug=%21.15g\n",f1iter,pp[RHO],pp[UU]);
6443  break;
6444  }
6445  }
6446 
6447 
6448  *nummhdstepsreturn = (int)(nstroke-nstrokeorig); // get number of mhd inversion steps
6449  if(*nummhdstepsreturn>MAXMHDSTEPS){
6450  failreturn=0;
6451  break;
6452  }
6453 
6454 
6455  }// end loop over f1iter
6456  *f1itersreturn += f1iter;
6457 
6458 
6460  // break again out of total loop if broke in f1iter loop
6461  if(failreturn){
6462  prod0dualfprintf(debugfail>=DEBUGLEVELIMPSOLVERMORE,fail_file,"Breaking out of loop as think f1iter wanted us to.\n");
6463  break; // ok to break here and avoid saying this was best solution since unlikely will be best as f1 can't even be obtained. And so step shouldn't be taken as well.
6464  }
6465  else{// else if good f1
6466 
6468  //
6469  // Check if reached max f1 iterations
6470  //
6472  *nummhdstepsreturn = (int)(nstroke-nstrokeorig); // get number of mhd inversion steps
6473  if(f1iter==MAXF1TRIES || *nummhdstepsreturn>MAXMHDSTEPS){
6474 
6475  if(f1iter==MAXF1TRIES) if(debugfail>=2) dualfprintf(fail_file,"Reached MAXF1TRIES=%d (nummhdstepsreturn=%d: %d %d trueimpmaxiter=%d): fracdtuu0=%g nstep=%ld steppart=%d ijk=%d %d %d : iter=%d eomtype=%d baseitermethod=%d failreturn=%d\n",MAXF1TRIES,*nummhdstepsreturn,nstrokeorig,nstroke,trueimpmaxiter,fracdtuu0,nstep,steppart,ptrgeom->i,ptrgeom->j,ptrgeom->k,iter,eomtypelocal,*baseitermethod,failreturn);
6476  if(*nummhdstepsreturn>MAXMHDSTEPS) if(debugfail>=2) dualfprintf(fail_file,"Reached MAXMHDSTEPS=%d: fracdtuu0=%g nstep=%ld steppart=%d ijk=%d %d %d : iter=%d eomtype=%d baseitermethod=%d failreturn=%d\n",*nummhdstepsreturn,fracdtuu0,nstep,steppart,ptrgeom->i,ptrgeom->j,ptrgeom->k,iter,eomtypelocal,*baseitermethod,failreturn);
6477  if(havebackup){
6478  failreturn=FAILRETURNMODESWITCH; mathfailtype=20;
6479  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"SWITCHING MODE: Detected MAXF1TRIES\n");
6480  break; // ok to break, no better solution to store as best
6481  }
6482  else{
6483  failreturn=FAILRETURNGENERAL; mathfailtype=2;
6484  if(doingit==1) myexit(10000000); // DEBUG
6485  // Note that if inversion reduces to entropy or cold, don't fail, so passes until reached this point. But convergence can be hard if flipping around which EOMs for the inversion are actually used.
6486  break; // ok to break, no better solution to store as best
6487  }
6488  }
6489  else{
6490  // restore fracuup back to 1 since this is only meant to adjust how much go back to previous uu to be able to get f1 computed.
6491  // fracuup doesn't stay <1.0 because each attempt to get f1 is independent.
6492  // KORALNOTE: Perhaps reasonable and safer to keep fracuup as not reverted back to 1, since apparently unable to take full steps. This effectively damps stepping.
6493  fracuup=1.0;
6494  }
6495 
6496  // diagnose
6497  if(showmessagesheavy) PLOOP(pliter,pl) dualfprintf(fail_file,"i=%d ii=%d pl=%d f1=%g\n",ptrgeom->i,ii,pl,f1[pl]);
6498  }// else if f1 calculation didn't fail.
6499 
6500 
6501 
6502 
6504  //
6505  // get type of EOMTYPE
6506  //
6508  int eomcond=(eomtypelocal==EOMGRMHD || eomtypelocal==EOMDEFAULT && EOMDEFAULT==EOMGRMHD);
6509 
6510 
6512  //
6513  // see if should check convergence or check how solution is behaving.
6514  //
6516  checkconv=1;
6518  // if(fracuup!=1.0){
6519  // if(fabs(fracuup-1.0)>10.0*NUMEPSILON){
6520  if(fracuup<1.0){
6521  // try increasing amount of uu or pp used
6522  checkconv=0;
6523  }
6525  // if(fracdtuu0!=1.0){
6526  // if(fabs(fracdtuu0-1.0)>10.0*NUMEPSILON && changeotherdt){
6527  if(fracdtuu0<1.0){
6528  checkconv=0;
6529  }
6531  // if(fracdtG!=1.0){
6532  // if(fabs(fracdtG-1.0)>10.0*NUMEPSILON && changeotherdt){
6533  if(fracdtG<1.0 && changeotherdt){
6534  checkconv=0;
6535  }
6537  if(iter<mtd.BEGINNORMALSTEPS) checkconv=0; // don't check actual convergence till doing full steps
6539 
6540 
6541 
6543  //
6544  // get error using f1 and f1norm
6545  //
6547  // int convreturnf1=f_error_check(showmessages, showmessagesheavy, iter, trueimptryconv, trueimptryconvabs, realdt, DIMTYPEFCONS,eomtypelocal , *radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,pp,piin,f1,f1norm,f1report,Uiin,uu0,uu,ptrgeom,&errorabsf1[0],&errorabsf1[1],WHICHERROR,&mtd,&ru);
6548  // but don't break, since need to iterate a bit first and check |dU/U| and need to see if checkconv==1
6549  FTYPE numsub=0;
6550  suberrorabsf1=0.0; JACLOOPSUBERROR(jj,ru.startjac,ru.endjac){
6551  suberrorabsf1 += fabs(f1report[ru.erefU[jj]]); // e.g. may only be energy error or only momentum error.
6552  numsub += 1.0;
6553  }
6554 
6555 
6556 
6557  // DEBUG STUFF
6558 #if(DEBUGMAXITER)
6559  if(dampattempt==0){
6560  PLOOP(pliter,pl) pppreholdlist[debugiter][pl]=pp[pl]; // just default dummy value in case break
6561  PLOOP(pliter,pl) ppposholdlist[debugiter][pl]=pp[pl]; // just default dummy value in case break
6562  if(DEBUGMAXITERVELOCITY==1){
6563  SLOOPA(jj){
6564  pppreholdlist[debugiter][U1+jj-1]=q->ucon[jj];
6565  pppreholdlist[debugiter][URAD1+jj-1]=q->uradcon[jj];
6566  ppposholdlist[debugiter][U1+jj-1]=q->ucon[jj];
6567  ppposholdlist[debugiter][URAD1+jj-1]=q->uradcon[jj];
6568  }
6569  }
6570  PLOOP(pliter,pl) f1reportlist[debugiter][pl]=f1report[pl];
6571  PLOOP(pliter,pl) f1list[debugiter][pl]=f1[pl];
6572  realiterlist[debugiter]=iter;
6573  DLOOP(jj,kk) jaclist[debugiter][jj][kk]=BIG; // just default dummy value in case break
6574  implicititerlist[debugiter]=mtd.implicititer;
6575  implicitferrlist[debugiter]=mtd.implicitferr;
6576  fracdamplist[0]=fracdtuu0;
6577  fracdamplist[1]=fracdtG;
6578  fracdamplist[2]=DAMPFACTOR;
6579  }
6580  errorabsf1list[debugiter]=errorabsf1[0];
6581  errorallabsf1list[debugiter]=errorabsf1[1];
6582 #else
6583  errorabsf1list[debugiter]=errorabsf1[0];
6584  errorallabsf1list[debugiter]=errorabsf1[1];
6585 #endif
6586 
6587 
6588 
6590  //
6591  // If error dropped below tolerance for this sub-matrix iteration mode, then continue to next level.
6592  //
6594  // check if energy only iteration has error that has dropped below tolerance, then can move on to
6595  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){
6596  FTYPE errorabs3=0.0; int testi;
6597  for(testi=1;testi<=3;testi++) errorabs3 += fabs(f1report[ru.irefU[testi]]);
6598  FTYPE errorneed=((FTYPE)(3+2)*trueimptryconv);
6599  if(errorabs3<errorneed){
6600  if(iter<=mtd.ENDMOMSTEPS){ iter=mtd.BEGINENERGYSTEPS-1; continue;} // force as if already doing energy steps. If already next iteration is to be this energy step, then no skipping needed.
6601  // continue assumes not triggered when iter>trueimpmaxiter
6602  }
6603  }
6604  // check if energy only iteration has error that has dropped below tolerance, then can move on to
6605  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){
6606  // if(f1report[ru.irefU[0]]==BIG){ dualfprintf(fail_file,"FUDGE\n"); }
6607  // SUPERGODMARK: valgrind says belw is undefined, but don't see it.
6608  FTYPE errorabs1=0.0; int testi;
6609  for(testi=1;testi<=1;testi++) errorabs1 += fabs(f1report[ru.irefU[testi]]);
6610  FTYPE errorneed=((FTYPE)(1+2)*trueimptryconv);
6611  if(errorabs1<errorneed){
6612  if(iter<=mtd.ENDENERGYSTEPS){ iter=mtd.BEGINFULLSTEPS-1; continue;} // force as if already doing normal steps. If already next iteration is to be normal step, no need to skip.
6613  // continue assumes not triggered when iter>trueimpmaxiter
6614  }
6615  }
6616 
6617 
6618 
6619 
6620 
6621 
6622 
6624  //
6625  // PRE NEWTON ADJUSTMENTS
6626  //
6628 
6629 #define ERRORJUMPCHECK 0 // no longer needed with error trend check, and expensive if u_g or Erf try to be <0 since hits continue.
6630  // whether to check if error jumps up, between last and current step, in irefU[0] -- u_g for QTYPMHD method. If so, backs-up step a bit for all quantities iterated and try to get error again
6631 #define BUFFERITER 0 // how many iterations to wait until start to check how error is doing. When switching iteration methods, error will often rise initially in f1[0], but that's ok. But can temper jump by bridging used pp,uu, so ok to keep as 0 perhaps.
6632  // check if doing energy stepping and error jumped up too much
6633 #define NUMJUMPCHECKSMAX 5 // must limit, else if really drops-out and can't help, need to just accept.
6634 #if(ERRORJUMPCHECK)
6635  if(numjumpchecks<NUMJUMPCHECKSMAX){
6636  if(iter>=mtd.BEGINENERGYSTEPS+BUFFERITER && iter<=mtd.ENDENERGYSTEPS || iter>=mtd.BEGINFULLSTEPS+BUFFERITER && iter<=mtd.ENDFULLSTEPS){// now all steps beyond energy
6637  if(
6638  (fabs(f1[ru.erefU[0]]/f1p[ru.erefU[0]])>FACTORBADJUMPERROR && fabs(f1report[ru.erefU[0]])>trueimptryconv)
6639  || (pp[URAD0]<10.0*ERADLIMIT) // expensive
6640  || (pp[UU]<10.0*UUMINLIMIT) // expensive
6641  ){
6642  // then pseudo-bisect (between zero and previous ok error case)
6643  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"pseudo-bisect: iter=%d f1=%g f1p=%g pp=%g ppp=%g pppp=%g ppppp=%g\n",iter,f1[ru.erefU[0]],f1p[ru.erefU[0]],pp[ru.irefU[0]],ppp[ru.irefU[0]],pppp[ru.irefU[0]],ppppp[ru.irefU[0]]);
6644  if(0){
6645  // doens't make sense in general
6646  // pp[ru.irefU[0]] = ppp[ru.irefU[0]] = pppp[ru.irefU[0]] = 0.5*(fabs(ppppp[ru.irefU[0]]));
6647  pp[ru.irefU[0]] = ppp[ru.irefU[0]] = 0.5*fabs(pppp[ru.irefU[0]]);
6648  uu[ru.irefU[0]] = uup[ru.irefU[0]] = 0.5*fabs(uupp[ru.irefU[0]]);
6649  }
6650  else{
6651  // half-way between current (pp and ppp are same current primitve) and last primitive
6652  // uu and pp won't be consistent, but when get to f_implicit(), as continue forces, this will be done.
6653  PLOOP(pliter,pl) pp[pl] = 0.75*pppp[pl] + 0.25*ppp[pl];
6654  PLOOP(pliter,pl) uu[pl] = 0.75*uupp[pl] + 0.25*uup[pl];
6655  }
6656  // update debug with modifications
6657 #if(DEBUGMAXITER)
6658  if(dampattempt==0){
6659  PLOOP(pliter,pl) pppreholdlist[debugiter][pl]=pp[pl];
6660  PLOOP(pliter,pl) ppposholdlist[debugiter][pl]=pp[pl];
6661  if(DEBUGMAXITERVELOCITY==1){
6662  SLOOPA(jj){
6663  pppreholdlist[debugiter][U1+jj-1]=q->ucon[jj];
6664  pppreholdlist[debugiter][URAD1+jj-1]=q->uradcon[jj];
6665  ppposholdlist[debugiter][U1+jj-1]=q->ucon[jj];
6666  ppposholdlist[debugiter][URAD1+jj-1]=q->uradcon[jj];
6667  }
6668  }
6669  DLOOP(jj,kk) jaclist[debugiter][jj][kk]=iJ[ru.irefU[jj]][ru.erefU[kk]];
6670  implicititerlist[debugiter]=mtd.implicititer;
6671  implicitferrlist[debugiter]=mtd.implicitferr;
6672  fracdamplist[0]=fracdtuu0;
6673  fracdamplist[1]=fracdtG;
6674  fracdamplist[2]=DAMPFACTOR;
6675  }
6676 #endif
6677 
6678 
6679  // need to get new error function so can take step based upon this as reference!
6680  if(iter>trueimpmaxiter){
6681  prod0dualfprintf(debugfail>=DEBUGLEVELIMPSOLVERMORE,fail_file,"iter=%d>%d\n",iter,trueimpmaxiter);
6682  }
6683  else{
6684  // continue assumes not triggered when iter>trueimpmaxiter
6685  numjumpchecks++;
6686  if(numjumpchecks<NUMJUMPCHECKSMAX) continue; // head to start of loop to iter++ and get new error function.
6687  }
6688  }
6689  }
6690  }
6691 #endif // end if ERRORJUMPCHECK
6692 
6693 
6694 
6695 
6696 
6697 
6698  // only check convergence or check the properties of the solution if checkconv==1
6699  if(checkconv){
6701  //
6702  // see if pre-convergence (happens if force is small or no force at all. Can't necessarily continue since Jacobian can require arbitrarily large dU on fluid and fail to invert even if no fluid-radiation interaction!
6703  //test pre-convergence using initial |dU/U|
6704  // KORALTODO: This isn't a completely general error check since force might be large for fluid that needs itself to have more accuracy, but if using ~NUMEPSILON, won't resolve 4-force of radiation on fluid to better than that.
6705  //
6707  FTYPE LOCALPREIMPCONV=MIN(10.0*NUMEPSILON,trueimptryconv); // more strict than later tolerance
6708  FTYPE LOCALPREIMPCONVABS=(FTYPE)(NDIM+2)*LOCALPREIMPCONV; // more strict than later tolerance
6709  if(STOPIFVERYLOWERROR && errorabsf1[WHICHERROR]<=LOCALPREIMPCONVABS){
6710  earlylowerror=1;
6711  }
6712  // see if error on iterated quantities has already gone near/below machine precision. If so, can't do any better with total error, so stop.
6713  if(STOPIFITERLOWERROR && WHICHERROR==1 && errorabsf1[0]<=LOCALPREIMPCONVABS){
6714  lowitererror=1; // __WORKINGONIT__: makes use urad alot and why?
6715  }
6716 
6717 
6718 
6720  //
6721  // try to get best solution (should be based upon immediate f_error_check(uu,pp,errorabsf1)
6722  //
6723  // store error and solution in case eventually lead to max iterations and actually get worse error
6724  // f1 based
6725  //
6727  errorabsbest[0]=0.0; JACLOOPFULLERROR(itermode,jj,ru.startjac,ru.endjac) errorabsbest[0] += fabs(lowestf1report[ru.erefU[jj]]);
6728  errorabsbest[1]=0.0; JACLOOPSUPERFULL(pliter,pl,*eomtype,*baseitermethod,*radinvmod) errorabsbest[1] += fabs(lowestf1report[pl]);
6729  if(errorabsbest[WHICHERROR]>errorabsf1[WHICHERROR] && isfinite(errorabsf1[WHICHERROR]) && (itermode==ITERMODECOLD || pp[RHO]>0.0 && pp[UU]>0.0 && pp[PRAD0]>0.0)){
6730  PLOOP(pliter,pl) bestuu[pl]=uu[pl];
6731  PLOOP(pliter,pl) bestpp[pl]=pp[pl];
6732  PLOOP(pliter,pl) lowestf1[pl]=f1[pl];
6733  PLOOP(pliter,pl) lowestf1norm[pl]=f1norm[pl];
6734  PLOOP(pliter,pl) lowestf1report[pl]=f1report[pl];
6735  errorabsbest[0]=errorabsf1[0];
6736  errorabsbest[1]=errorabsf1[1];
6737  radinvmodbest=*radinvmod;
6738  gotbest=1;
6739  }
6740 
6741 
6742  if(earlylowerror){
6743  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"Early low error=%g %g : iter=%d\n",errorabsf1[0],errorabsf1[1],iter);
6744  // not failure.
6745  break;
6746  }
6747  if(lowitererror){
6748  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"Low iter error=%g %g : iter=%d\n",errorabsf1[0],errorabsf1[1],iter);
6749  // not failure.
6750  break;
6751  }
6752 
6753 
6754  if(convreturnf1){
6755  break; // then converged already and no need to take a step (saves time)
6756  }
6757 
6758 
6759 
6760 
6761 
6762 
6763 
6765  //
6766  // See if error is dropping as expected
6767  // Trying to avoid excessive unhelpful iterations
6768  //
6770 
6771 #define CHECKDECREASE0 5
6772 #define CHECKDECREASEAVGNUM 3 // should be less than CHECKDECREASE0
6773 #define CHECKDECFACTOR (0.5) // i.e. should drop by this factor compared to older average
6774  if(debugiter>=mtd.BEGINNORMALSTEPS+CHECKDECREASE0){
6775  int ci;
6776  FTYPE avgerror[NUMERRORTYPES];
6777  avgerror[0]=avgerror[1]=0.0;
6778  for(ci=0;ci<CHECKDECREASEAVGNUM;ci++) avgerror[0] += errorabsf1list[debugiter-CHECKDECREASE0+ci];
6779  for(ci=0;ci<CHECKDECREASEAVGNUM;ci++) avgerror[1] += errorallabsf1list[debugiter-CHECKDECREASE0+ci];
6780  avgerror[0]/=(CHECKDECREASEAVGNUM);
6781  avgerror[1]/=(CHECKDECREASEAVGNUM);
6782  FTYPE currenterror[NUMERRORTYPES];
6783  currenterror[0]=errorabsf1list[debugiter];
6784  currenterror[1]=errorallabsf1list[debugiter];
6785  //
6786  // check both errors to ensure they are decreasing
6787  int cond1=(currenterror[0]>CHECKDECFACTOR*avgerror[0] || currenterror[1]>CHECKDECFACTOR*avgerror[1])&&(WHICHERROR==1);
6788  int cond2=(currenterror[0]>CHECKDECFACTOR*avgerror[0])&&(WHICHERROR==0);
6789  if(cond1 || cond2){
6790 
6791  if(havebackup){
6792  failreturn=FAILRETURNMODESWITCH; mathfailtype=80;
6793  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"SWITCHING MODE: Detected did not decrease error\n");
6794  // if want to ensure should have gotten solution, should still report
6795  }
6796  else{
6797  // then aborting due to error alone even without backup
6798  canbreak=4; // use same canbreak as below
6799  mathfailtype=81;
6800  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"Aborting even without backup because error not decreasing\n");
6801  // no failure or switch.
6802  }
6803  break;
6804 
6805  }// end if current error too large compared to older average error
6806  }// end if large enough iterations so can check how error is trending, to avoid many iterations when error is not dropping enough to matter.
6807 
6808 
6809 
6810 
6811 
6813  //
6814  // check if error repeatedly rises
6815  // do this even if damping, since damping should only help get continuous reduction in error.
6816  //
6818 
6819  if(NUMNOERRORREDUCE && iter>=mtd.BEGINNORMALSTEPS){
6820  FTYPE errorneed=((FTYPE)(numsub+2)*trueimptryconv);
6821  FTYPE errorneedalt=(MAX(1E-8,errorneed));
6822  if(iter>NUMNOERRORREDUCE0 && suberrorabsf1>errorneed){ // no need to do this if actually error is below desired tolerance, hence second argument
6823  if(suberrorabsf1>=errorabspf1[0]) counterrorrose++;
6824  int allowedtoabort=(havebackup || havebackup==0 && ABORTBACKUPIFNOERRORREDUCE==1 && suberrorabsf1<errorneedalt);
6825  //+int allowedtoabort=(havebackup || havebackup==0 && ABORTBACKUPIFNOERRORREDUCE==1 && suberrorabsf1<errorneedalt || modemethodlocal==MODEPICKBEST || modemethodlocal==MODEPICKBESTSIMPLE || modemethodlocal==MODEPICKBESTSIMPLE2);
6826  if(counterrorrose>=NUMNOERRORREDUCE && allowedtoabort){ // would be risky to do abort if don't have backup, even if enter into limit cycle.
6827 
6828  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){
6829  if(iter<=mtd.ENDMOMSTEPS){ iter=mtd.BEGINENERGYSTEPS-1; continue;} // force as if already doing energy steps. If already next iteration is to be this energy step, then no skipping needed.
6830  }// end if doing momentum steps and error not decreasing fast enough, then skip to energy steps
6831  else if(itermode==ITERMODESTAGES && iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){
6832  if(iter<=mtd.ENDENERGYSTEPS){ iter=mtd.BEGINFULLSTEPS-1; continue;} // force as if already doing normal steps. If already next iteration is to be normal step, no need to skip.
6833  }// end if doing energy steps and error not decreasing fast enough, then skip to normal steps
6834  else{// else if normal step
6835 
6836  if(havebackup){
6837  failreturn=FAILRETURNMODESWITCH; mathfailtype=80;
6838  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"SWITCHING MODE: Detected did not decrease error %d times at iter=%d : suberrorabsf1=%g errorabspf1=%g\n",counterrorrose,iter,suberrorabsf1,errorabspf1[0]);
6839  // if want to ensure should have gotten solution, should still report
6840  }
6841  else{
6842  // then aborting due to error alone even without backup
6843  canbreak=2;
6844  mathfailtype=81;
6845  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"Aborting even without backup because error oscillated (iter=%d) and suberrorabsf1=%g errorabsf1[0,1]=%g %g\n",iter,suberrorabsf1,errorabsf1[0],errorabsf1[1]);
6846  // no failure or switch.
6847  }
6848  break;
6849  }
6850  }// end if normal step
6851  }
6852  }
6853 
6854 
6855 
6857  //
6858  // check if error isn't decreasing enough for be interesting
6859  // but don't check on error if holding on u_g>0 since error can be bad until settle to near root.
6860  // and don't do this check if damping, since if damping really want to try harder.
6861  //
6863  if(NUMPRIORERRORS>0 && holdingaspositive==0 && dampattempt==0){
6864  if(priorerrorscount>=NUMPRIORERRORSITER0){
6865  FTYPE erroraverage=0.0; int numerroraverage=0;
6866  for(itererror=1;itererror<MIN(priorerrorscount,NUMPRIORERRORS);itererror++){ erroraverage += errorabspf1[itererror]; numerroraverage++;} erroraverage/=((FTYPE)numerroraverage);
6867  FTYPE changerequired;
6868  if(dampattempt==0) changerequired=PRIORERRORCHANGEREQUIRED;
6869  else if(dampattempt==1) changerequired=0.7;
6870  else if(dampattempt==2) changerequired=0.8;
6871  else if(dampattempt==3) changerequired=0.9;
6872  else changerequired=0.95;
6873  FTYPE errorneed=((FTYPE)(numsub+2)*trueimptryconv);
6874  if(suberrorabsf1/erroraverage>changerequired && suberrorabsf1>errorneed){
6875 
6876  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){
6877  if(iter<=mtd.ENDMOMSTEPS){ iter=mtd.BEGINENERGYSTEPS-1; continue;} // force as if already doing energy steps. If already next iteration is to be this energy step, then no skipping needed.
6878  }// end if doing momentum steps and error not decreasing fast enough, then skip to energy steps
6879  else if(itermode==ITERMODESTAGES && iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){
6880  if(iter<=mtd.ENDENERGYSTEPS){ iter=mtd.BEGINFULLSTEPS-1; continue;} // force as if already doing normal steps. If already next iteration is to be normal step, no need to skip.
6881  }// end if doing energy steps and error not decreasing fast enough, then skip to normal steps
6882  else{
6883  canbreak=3;
6884  if(debugfail>=DEBUGLEVELIMPSOLVER){
6885  dualfprintf(fail_file,"Error is not decreasing sufficiently fast: iter=%d priorerrorscount=%d suberrorabsf1=%g\n",iter,priorerrorscount,suberrorabsf1);
6886  for(itererror=1;itererror<MIN(priorerrorscount,NUMPRIORERRORS);itererror++) dualfprintf(fail_file,"errorabspf1[%d]=%g\n",itererror,errorabspf1[itererror]);
6887  }
6888  break;
6889  }// end if doing normal steps and error not decreasing fast enough
6890  }// end if error not decreasing enough and also higher than desired tolerance in error
6891  }// end if enough prior errors to make average measurement of past error
6892  priorerrorscount++;
6893  }
6894 
6895 
6896 
6897 
6898 
6899  }// end if checkconv==1
6900 
6901 
6902 
6903 
6905  //
6906  // See if solution has nan'ed or inf'ed out.
6907  //
6909  if(IMPUTYPE(mtd.implicititer)){
6910  notfinite = !isfinite(uu[ru.irefU[0]])|| !isfinite(uu[ru.irefU[1]])|| !isfinite(uu[ru.irefU[2]])|| !isfinite(uu[ru.irefU[3]]) || !isfinite(uup[ru.irefU[0]])|| !isfinite(uup[ru.irefU[1]])|| !isfinite(uup[ru.irefU[2]])|| !isfinite(uup[ru.irefU[3]]);
6911  }
6912  else if(IMPPTYPE(mtd.implicititer)){
6913  notfinite = !isfinite(pp[ru.irefU[0]])|| !isfinite(pp[ru.irefU[1]])|| !isfinite(pp[ru.irefU[2]])|| !isfinite(pp[ru.irefU[3]]) || !isfinite(ppp[ru.irefU[0]])|| !isfinite(ppp[ru.irefU[1]])|| !isfinite(ppp[ru.irefU[2]])|| !isfinite(ppp[ru.irefU[3]]);
6914  }
6915 
6916 
6917 
6919  //
6920  // continue with computing Jacobian and Newton step if origin point for error function didn't nan'out or inf'out.
6921  //
6923  if(!notfinite){
6924 
6925 
6926  if(SKIPJACCOMPUTE==0 || SKIPJACCOMPUTE==1 && (iter<=SKIPJACITER || iter>SKIPJACITER && iter%SKIPJACFACTOR==0)){ // only get new Jacobian before 5th iteration and then only if every 3rd iteration since assume Jacobian itself doesn't change so rapidly.
6927 
6929  //
6930  // get Jacobian and inversion Jacobian
6931  //
6933  // eomtypelocal=*eomtype; // re-chose default each time. No, stick with what f1 reduced to for consistency.
6934  // dualfprintf(fail_file,"iJ call: iter=%d\n",iter);
6935 
6936  // assume as error gets small, function becomes linear and can use smaller delta for Jacobian
6937  if(errorabsf1[WHICHERROR]<ERRORFORIMPEPSSMALL) impepsjac=IMPEPSSMALL;
6938  else impepsjac=IMPEPSLARGE;
6939  int dimtypef=DIMTYPEFCONS;
6940  int failreturniJ=get_implicit_iJ(allowbaseitermethodswitch, failreturnallowableuse, showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, baseitermethod, fracenergy, dissmeasure, impepsjac, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, iter, errorabsf1[0], errorabsf1[1], WHICHERROR, dimtypef, dimfactU, Uiin, uu, uup, uu0, piin, pp, ppp, fracdtG, realdt, ptrgeom, q, f1, f1norm, iJ, nummhdinvsreturn,&mtd,&ru);
6941 
6942  if(failreturniJ!=0){
6943  if(havebackup){
6944  failreturn=FAILRETURNMODESWITCH; mathfailtype=30;
6945  prod0dualfprintf(debugfail>=DEBUGLEVELIMPSOLVER,fail_file,"SWITCHING MODE: Detected bad Jacobian\n");
6946  break;
6947  }
6948  else{
6949  failreturn=FAILRETURNJACISSUE; mathfailtype=12;
6950  break;
6951  }
6952  }
6953 
6954 
6955 
6956 #if(PRODUCTION==0)
6957  if(showmessagesheavy){
6958  int iii,jjj;
6959  JACLOOP2D(iii,jjj,ru.startjac,ru.endjac) dualfprintf(fail_file,"iJ[i %d][e %d]=%g\n",iii,jjj,iJ[ru.irefU[iii]][ru.erefU[jjj]]);
6960  }
6961 #endif
6962 
6963 
6964  }
6965 
6966 
6967 
6969  //
6970  // Newton step (uup or ppp)
6971  //
6972  // DAMPFACTOR unused so far because don't know a priori whether to damp. fracuup does post-inversion effective damping of this Newton step.
6973  // Newton step: x = x0 - (df/dx)^{-1}|_{x=x0} f(x0)
6974  //
6975  // Only updates 4D part of NPR data
6976  //
6978 
6979 
6981  //
6982  // ITERATING U
6983  //
6985  if(IMPUTYPE(mtd.implicititer)){
6986  PLOOP(pliter,pl) uu[pl] = uup[pl];
6987  JACLOOP2D(ii,jj,ru.startjac,ru.endjac) uu[ru.irefU[ii]] -= DAMPFACTOR*iJ[ru.irefU[ii]][ru.erefU[jj]]*f1[ru.erefU[jj]];
6988 
6989  if(POSTNEWTONCONVCHECK==2){
6990  // check if any actual changes in primitives. If none, then have to stop.
6991  FTYPE diffuu=0.0,sumuu=0.0;
6992  PLOOP(pliter,pl){
6993  diffuu += fabs(uu[pl]-uup[pl]);
6994  sumuu += fabs(uu[pl])+fabs(uup[pl]);
6995  }
6996  if(diffuu<DIFFXLIMIT*sumuu){
6997  convreturnf3limit=1;
6998  }
6999  }
7000 
7001 
7002 #if(PRODUCTION==0)
7003  if(showmessagesheavy) dualfprintf(fail_file,"POSTDX: uu: %g %g %g %g : uup=%g %g %g %g\n",uu[ru.irefU[0]],uu[ru.irefU[1]],uu[ru.irefU[2]],uu[ru.irefU[3]],uup[ru.irefU[0]],uup[ru.irefU[1]],uup[ru.irefU[2]],uup[ru.irefU[3]]);
7004 #endif
7005 
7006 
7007  }// end iterating U
7008 
7009 
7011  //
7012  // ITERATING P
7013  //
7015  else if(IMPPTYPE(mtd.implicititer)){
7016 
7017  if(NEWJONHOLDPOS==0){
7018  PLOOP(pliter,pl) pp[pl]=ppp[pl];
7019  JACLOOP2D(ii,jj,ru.startjac,ru.endjac){
7020  pp[ru.irefU[ii]] -= DAMPFACTOR*iJ[ru.irefU[ii]][ru.erefU[jj]]*f1[ru.erefU[jj]];
7021  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"added to ppp=%21.15g ii=%d jj=%d irefU=%d an amount of negative %21.15g\n",ppp[ru.irefU[ii]],ii,jj,ru.irefU[ii],DAMPFACTOR*iJ[ru.irefU[ii]][ru.erefU[jj]]*f1[ru.erefU[jj]]);
7022  }
7023  }
7024  else{
7025  // if u_g (or Erf)<0, then shift entire jacobian to make smaller changes
7026 
7027  FTYPE dpp[NPR]={0.0};
7028  PLOOP(pliter,pl) pp[pl]=ppp[pl];
7029  JACLOOP2D(ii,jj,ru.startjac,ru.endjac){
7030  dpp[ru.irefU[ii]] += -DAMPFACTOR*iJ[ru.irefU[ii]][ru.erefU[jj]]*f1[ru.erefU[jj]];
7031  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"added to ppp=%21.15g ii=%d jj=%d irefU=%d an amount of negative %21.15g\n",ppp[ru.irefU[ii]],ii,jj,ru.irefU[ii],DAMPFACTOR*iJ[ru.irefU[ii]][ru.erefU[jj]]*f1[ru.erefU[jj]]);
7032  }
7033  JACLOOP(ii,ru.startjac,ru.endjac){
7034  pp[ru.irefU[ii]] += dpp[ru.irefU[ii]];
7035  }
7036 
7037  if(ru.startjac==0){
7038  ii=0;
7039  if(pp[ru.irefU[ii]]<=0.0){
7040 #if(0)
7041  FTYPE ppbad[NPR];
7042  PLOOP(pliter,pl) ppbad[pl]=pp[pl];
7043  // rescale iJ so u_g -> u_g0/2 instead (or for Erf)
7044  PLOOP(pliter,pl) pp[pl]=ppp[pl];
7045  FTYPE REDAMP=fabs(+0.5*ppp[UU]/dpp[UU])*DAMPFACTOR; // KORALTOD: inverted damp. Sometimes works, sometimes bad.
7046  JACLOOP2D(ii,jj,ru.startjac,ru.endjac){
7047  pp[ru.irefU[ii]] += REDAMP*iJ[ru.irefU[ii]][ru.erefU[jj]]*f1[ru.erefU[jj]];
7048  }
7049 #else
7050  pp[ru.irefU[ii]]=ppp[ru.irefU[ii]]; // super hold, works just as well as inverted damp.
7051 #endif
7052  }
7053  }
7054 
7055  }
7056 
7057 
7058 
7059 
7060  // DEBUG: store steps in case hit max iter and want to debug
7061 #if(DEBUGMAXITER)
7062  if(dampattempt==0){
7063  PLOOP(pliter,pl) pppreholdlist[debugiter][pl]=pp[pl];
7064  if(DEBUGMAXITERVELOCITY==1){
7065  SLOOPA(jj){
7066  pppreholdlist[debugiter][U1+jj-1]=q->ucon[jj];
7067  pppreholdlist[debugiter][URAD1+jj-1]=q->uradcon[jj];
7068  }
7069  }
7070  DLOOP(jj,kk) jaclist[debugiter][jj][kk]=iJ[ru.irefU[jj]][ru.erefU[kk]];
7071  implicititerlist[debugiter]=mtd.implicititer;
7072  implicitferrlist[debugiter]=mtd.implicitferr;
7073  fracdamplist[0]=fracdtuu0;
7074  fracdamplist[1]=fracdtG;
7075  fracdamplist[2]=DAMPFACTOR;
7076  }
7077 #endif
7078 
7079 
7080 
7081 
7083  //
7084  // POST NEWTON ADJUSTMENTS
7085  //
7087 
7088 
7089 
7090  // HOLD TT-iterated quantity or momentum-iterated quantity in initial steps
7091  if(RAMESHFIXEARLYSTEPS){
7092  // RAMESH HOLD
7093  if(iter<RAMESHFIXEARLYSTEPS) pp[ru.irefU[0]]=ppp[ru.irefU[0]]; // don't trust first Newton step in u_g, Erf, or S
7094  else if(iter==RAMESHFIXEARLYSTEPS) SLOOPA(jj) pp[ru.irefU[jj]]=ppp[ru.irefU[jj]]; // don't trust second Newton step in velocity-momentum.
7095 
7096  if(pp[RHO]<=0.0||pp[UU]<=0.0){
7097  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"Detected negative rho=%21.15g ug=%21.15g\n",iter,pp[RHO],pp[UU]);
7098  }
7099  }// end Ramesh hold
7100 
7101 
7102 
7103 
7104 
7105 
7107  //
7108  // check if u_g,Erf<0. Do even if RAMESHFIXEARLYSTEPS going or even if checkconv==0
7109  //
7111  // FTYPE umin=10.0*calc_PEQ_ufromTrho(TEMPMIN,fabs(pp[RHO]));
7112  if(pp[ru.irefU[0]]<=0.0 && (IMPPTYPE(mtd.implicititer)&& *baseitermethod!=QTYENTROPYPMHD)){ // don't consider mtd.implicititer==QTYENTROPYPMHD since S can be positive or negative. Would only be unphysical or absolute-limited if the related u_g<0 or rho<0.
7113  if(JONHOLDPOS){
7114 
7115 #if(1)
7116  holdingaspositive=0; // default
7117  if(countholdpositive<NUMHOLDTIMES){
7118  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"HOLDING: Detected unphysical iter=%d countholdpositive=%d : pp[ru.irefU[0]]=%g : ijknstepsteppart=%d %d %d %ld %d\n",iter,countholdpositive,pp[ru.irefU[0]],ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
7119  //pp[ru.irefU[0]]=MAX(100.0*NUMEPSILON*fabs(pp[RHO]),fabs(ppp[ru.irefU[0]])); // hold as positive -- ppp might be too large so hold might be too aggressive to be useful.
7120  // if(gotbest) umin=MAX(umin,0.5*fabs(pp[UU])); // override with last best version of u_g, because using very minimum leads to jump in behavior. // causes problems, leads to many high error events.
7121  //pp[ru.irefU[0]]=umin; // hold as positive.
7122  pp[ru.irefU[0]]=0.5*fabs(ppp[ru.irefU[0]]); // just drop by half of positive value of *previous* value, not of negative value.
7123  countholdpositive++;
7124  holdingaspositive=1;
7125  }
7126 #else
7127 #define NUMITERHOLD (eomcond ? 2 : 4)
7128  if(holdingaspositive==0 || holdingaspositive==1 && iter<iterhold+NUMITERHOLD){
7129  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"HOLDING: Detected unphysical iter=%d iterhold+NUMITERHOLD=%d holdingaspositive=%d : pp[ru.irefU[0]]=%g : ijknstepsteppart=%d %d %d %ld %d\n",iter,iterhold+NUMITERHOLD,holdingaspositive,pp[ru.irefU[0]],ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
7130  if(holdingaspositive==0) iterhold=iter;
7131  // else holdingaspositive=1;
7132  holdingaspositive=1;
7133  // pp[ru.irefU[0]]=100.0*NUMEPSILON*fabs(pp[RHO]); // hold as positive just one iteration
7134  // if(gotbest) umin=MAX(umin,0.5*fabs(pp[UU])); // override with last best version of u_g, because using very minimum leads to jump in behavior. // causes problems, leads to many high error events.
7135  //pp[ru.irefU[0]]=umin; // hold as positive
7136  pp[ru.irefU[0]]=0.5*fabs(ppp[ru.irefU[0]]); // just drop by half of positive value of *previous* value, not of negative value.
7137  }
7138 #endif
7139  else{// then exceeding hold attempts
7140 
7141  // if pre-normal step, skip to next type of step because non-normal step seems to want wrong/bad u_g anyways.
7142  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){
7143  // revert to previous stepping's u_g, since using modified u_g (after u_g<0) should be bad.
7144  PLOOP(pliter,pl){
7145  pp[pl] = pppriorsteptype[pl];
7146  uu[pl] = uupriorsteptype[pl];
7147  }
7148  iter=mtd.BEGINENERGYSTEPS-1;
7149  continue;
7150  }
7151  else if(itermode==ITERMODESTAGES && iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){
7152  // revert previous stepping's u_g, since using modified u_g (after u_g<0) should be bad.
7153  PLOOP(pliter,pl){
7154  pp[pl] = pppriorsteptype[pl];
7155  uu[pl] = uupriorsteptype[pl];
7156  }
7157  iter=mtd.BEGINFULLSTEPS-1;
7158  continue;
7159  }
7160  else{// else doing normal steps
7161  pp[ru.irefU[0]]=0.5*fabs(ppp[ru.irefU[0]]); // just drop by half of positive value of *previous* value, not of negative value.
7162  if(DOFINALCHECK){
7163  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"Unable to hold off u_g<0, setting canbreak=1 and letting finalchecks confirm error is good or bad. iter=%d\n",iter);
7164  canbreak=1; // just break since might be good (or at least allowable) error still. Let final error check handle this.
7165  // not fail.
7166  mathfailtype=89;
7167  break;
7168  }
7169  else if(havebackup){
7170  failreturn=FAILRETURNMODESWITCH; mathfailtype=90;
7171  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"SWITCHING MODE: Detected bad u_g\n");
7172  break;
7173  }
7174  else{
7175  // then full failure
7176  failreturn=FAILRETURNGENERAL; mathfailtype=10;
7177  break;
7178  }
7179  }// end else normal step
7180  } // if beyond hold counts allowed
7181  } // end if JONHOLDPOS
7182  else{// not using JONHOLDPOS
7183  // if pre-normal step, skip to next type of step because non-normal step may have wrong u_g anyways.
7184  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){ iter=mtd.BEGINENERGYSTEPS-1; continue; }
7185  else if(itermode==ITERMODESTAGES && iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){ iter=mtd.BEGINFULLSTEPS-1; continue; }
7186  else{// else doing normal steps
7187  if(havebackup){
7188  failreturn=FAILRETURNMODESWITCH; mathfailtype=90;
7189  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"SWITCHING MODE: Detected unphysical pp[ru.irefU[0]]: iter=%d\n",iter);
7190  break;
7191  }
7192  }
7193  }// else if not using JONHOLDPOS
7194  }// end if u_g<0 and iterating primitives
7195  else{
7196  // if u_g>0, not holding.
7197  holdingaspositive=0;
7198  }
7199 
7200 
7201 
7202 
7203  // DEBUG: store steps in case hit max iter and want to debug
7204 #if(DEBUGMAXITER)
7205  if(dampattempt==0){
7206  PLOOP(pliter,pl) ppposholdlist[debugiter][pl]=pp[pl];
7207  if(DEBUGMAXITERVELOCITY==1){
7208  SLOOPA(jj){
7209  ppposholdlist[debugiter][U1+jj-1]=q->ucon[jj];
7210  ppposholdlist[debugiter][URAD1+jj-1]=q->uradcon[jj];
7211  }
7212  }
7213  }
7214 #endif
7215 
7216 
7217 
7218  // determine if holding so post-newton checks know.
7219  notholding=(RAMESHFIXEARLYSTEPS && iter>=RAMESHFIXEARLYSTEPS || RAMESHFIXEARLYSTEPS==0) && (JONHOLDPOS && holdingaspositive==0 || JONHOLDPOS==0);
7220 
7221 
7222 
7224  //
7225  // POST NEWTON CHECKS
7226  //
7228 
7229 
7230  // only do post-newton checks if checking convergence allowed
7231  if(checkconv==1){
7232 
7233  // check if energy u_g too often bad compared to entropy u_g
7234  // assume this is only done after
7236  if((mtd.implicititer==QTYPMHD || mtd.implicititer==QTYPMHDENERGYONLY) && didentropyalready){
7237  if(notholding==1 || mtd.implicititer==QTYPMHD){ // if holding on energy equation, don't use this u_g check. But, if normal steps, then ignore holding and assume holding means u_g bad if on normal steps.
7238  if(badenergy(ptrgeom,pp,pborig)) countbadenergy++;
7239  if(countbadenergy>=RAMESHSTOPENERGYIFTOOOFTENBELOWENTROPY){
7240 
7241  // if pre-normal step, skip to next type of step because non-normal step may have wrong u_g anyways.
7242  if(itermode==ITERMODESTAGES && iter>=mtd.BEGINMOMSTEPS && iter<=mtd.ENDMOMSTEPS){ iter=mtd.BEGINENERGYSTEPS-1; continue; }
7243  else if(itermode==ITERMODESTAGES && iter>=mtd.BEGINENERGYSTEPS && iter<=mtd.ENDENERGYSTEPS){ iter=mtd.BEGINFULLSTEPS-1; continue; }
7244  else{// else doing normal steps
7245  // "switch" to entropy by just stopping trying to get energy solution
7246  failreturn=FAILRETURNMODESWITCH; mathfailtype=100;
7247  prod0dualfprintf(debugfail>=DEBUGLEVELIMPSOLVER,fail_file,"SWITCHING MODE: Detected entropy u_g preferred consistently: iter=%d: %g %g\n",iter,pp[ru.irefU[0]],pborig[ru.irefU[0]]);
7248  break;
7249  }
7250  }// end if normal step
7251  }//end if at point where iterations can be considered
7252  }// whether have information necessary to check
7253  }// whether to check u_g energy vs. entropy
7254 
7255 
7256 
7257  if(POSTNEWTONCONVCHECK==2 && notholding==1){
7258  // check if any actual changes in primitives. If none, then have to stop.
7259  FTYPE diffpp=0.0,sumpp=0.0;
7260  PLOOP(pliter,pl){
7261  diffpp += fabs(pp[pl]-ppp[pl]);
7262  sumpp += fabs(pp[pl])+fabs(ppp[pl]);
7263  }
7264  if(diffpp<DIFFXLIMIT*sumpp){
7265  convreturnf3limit=1;
7266  }
7267  }
7268  }// end if checkconv==1
7269 
7270 
7271 
7272 
7273  prod0dualfprintf(showmessagesheavy,fail_file,"POSTDX: pp: %g %g %g %g : ppp=%g %g %g %g\n",pp[ru.irefU[0]],pp[ru.irefU[1]],pp[ru.irefU[2]],pp[ru.irefU[3]],ppp[ru.irefU[0]],ppp[ru.irefU[1]],ppp[ru.irefU[2]],ppp[ru.irefU[3]]);
7274 
7275 
7276 
7277  }// end if iterating primitves
7278 
7279 
7280 
7281 
7282 
7283 
7285  //
7286  // POST NEWTON ADJUSTMENTS part 2
7287  //
7289 
7290 
7291 
7292  // only do post-newton checks if checking convergence allowed
7293  if(checkconv==1){
7294 
7295 
7296 
7298  //
7299  // check if u_g<0 too often and know have entropy backup
7300  //
7302 
7303  if(IMPRADTYPEBASE(*baseitermethod)){//__WORKINGONIT__, might be too aggressive for PMHD method.
7304  // abort if too often hit negative u_g or Erf and know have entropy backup method.
7305 #define NUMUGNEGENERGY (3)
7306 
7307  if(pp[UU]<=10.0*UUMINLIMIT && *baseitermethod!=QTYENTROPYPMHD && iter>=mtd.BEGINNORMALSTEPS){
7308  countugnegative++;
7309  }
7310  else{
7311  // dualfprintf(fail_file,"NOTNEG: countugnegative=%d\n",countugnegative);
7312  }
7313 
7314  if(countugnegative>=NUMUGNEGENERGY && eomcond && (modemethodlocal==MODEPICKBEST || modemethodlocal==MODEPICKBESTSIMPLE || modemethodlocal==MODEPICKBESTSIMPLE2) && iter>=mtd.BEGINNORMALSTEPS){
7315  if(DOFINALCHECK){
7316  if(debugfail>=DEBUGLEVELIMPSOLVER) dualfprintf(fail_file,"2Unable to hold off u_g<0, setting canbreak=1 and letting finalchecks confirm error is good or bad. iter=%d\n",iter);
7317  canbreak=5; // just break since might be good (or at least allowable) error still. Let final error check handle this.
7318  // not fail.
7319  mathfailtype=89;
7320  break;
7321  }
7322  else if(havebackup){
7323  failreturn=FAILRETURNMODESWITCH; mathfailtype=90;
7324  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"2SWITCHING MODE: Detected bad u_g\n");
7325  break;
7326  }
7327  else{
7328  // then full failure
7329  failreturn=FAILRETURNGENERAL; mathfailtype=10;
7330  break;
7331  }
7332  }
7333  }
7334 
7335 
7336 
7337 
7338 
7339 
7340  FTYPE f3[NPR]={0},f3norm[NPR]={0};
7341  if(POSTNEWTONCONVCHECK==1 && notholding==1){
7342  int dimtypef3;
7344  //
7345  // test convergence after Newton step
7346  // test convergence using |dU/U|
7347  // KORALTODO: This isn't a completely general error check since force might be large for fluid. So using (e.g.) 1E-6 might still imply a ~1 or larger error for the fluid. Only down to ~NUMEPSILON will radiation 4-force be unresolved as fluid source term.
7348  // NOTE: Have to be careful with decreasing DAMPFACTOR or fracdtuu0 because can become small enough that apparently fake convergence with below condition, so only check for convergence if all DAMPs are 1.0.
7350  // 0 = conserved R^t_\nu type, 1 = primitive R^{ti} type
7351  if(IMPUTYPE(mtd.implicititer)){ // still considering iterate error
7352  dimtypef3=DIMTYPEFCONS;
7353  JACLOOPALT(ii,ru.startjac,ru.endjac){
7354  f3[ru.erefU[ii]]=(uu[ru.irefU[ii]]-uup[ru.irefU[ii]]);
7355  f3norm[ru.erefU[ii]]=fabs(uu[ru.irefU[ii]])+fabs(uup[ru.irefU[ii]]);
7356  }
7357  }
7358  else if(IMPPTYPE(mtd.implicititer)){ // still considering iterate error
7359  dimtypef3=DIMTYPEFPRIM;
7360  JACLOOPALT(ii,ru.startjac,ru.endjac){
7361  f3[ru.erefU[ii]]=(pp[ru.irefU[ii]]-ppp[ru.irefU[ii]]);
7362  f3norm[ru.erefU[ii]]=fabs(pp[ru.irefU[ii]])+fabs(ppp[ru.irefU[ii]]);
7363  }
7364  }
7365 
7366  // store error and solution in case eventually lead to max iterations and actually get worse error
7367  // f_error_check(uu0,uu) is ok to use since it just normalizes error
7368  int convreturnf3;
7369  FTYPE errorallabsf3; // not used
7370  convreturnf3=f_error_check(showmessages, showmessagesheavy, iter, trueimptryconv, trueimptryconvabs, realdt, dimtypef3,eomtypelocal ,*radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,pp,piin,f3,f3norm,f3report,Uiin,uu0,uu,ptrgeom,&errorabsf3,&errorallabsf3,WHICHERROR,&mtd,&ru);
7371  // while using f1 for true error, can't do better if f3 error is below near machine precision.
7372  convreturnf3limit=(errorabsf3<LOCALPREIMPCONVXABS);
7373  }
7374 
7375  if(POSTNEWTONCONVCHECK==0 || notholding==0){
7376  convreturnf3limit=0;
7377  }
7378 
7379 
7380 
7382  //
7383  // check convergence
7384  // then can check convergence: using f1 and f3limit
7385  //
7387  if(convreturnf1 || convreturnf3limit || canbreak){
7388 #if(PRODUCTION==0)
7389  if(debugfail>=DEBUGLEVELIMPSOLVERMORE){
7390  if(convreturnf3limit && debugfail>=3){
7391  dualfprintf(fail_file,"f3limit good\n");
7392  if(POSTNEWTONCONVCHECK==1) JACLOOPALT(ii,ru.startjac,ru.endjac) dualfprintf(fail_file,"ii=%d erefU[ii]=%d f3=%21.15g f3norm=%21.15g f3report=%21.15g\n",ii,ru.erefU[ii],f3[ru.erefU[ii]],f3norm[ru.erefU[ii]],f3report[ru.erefU[ii]]);
7393  }
7394  if(convreturnf1) dualfprintf(fail_file,"f1 good: ijknstepsteppart=%d %d %d %ld %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
7395  if(convreturnf3limit) dualfprintf(fail_file,"f3 good: ijknstepsteppart=%d %d %d %ld %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
7396  if(canbreak) dualfprintf(fail_file,"canbreak=%d good: ijknstepsteppart=%d %d %d %ld %d\n",canbreak,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
7397  }
7398 #endif
7399  // so done.
7400  break;
7401  }
7402  else{
7403  // then not done
7404  }
7405 
7406  } // end if checkconv==1
7407 
7408 #if(DOPERF)
7409  // only try low error if not too many iterations, otherwise drop trying quite as hard.
7410  if(iter>ITERATIONMARGINAL2 && (errorabsf1[WHICHERROR]<MIN(trueimpallowconvabs,IMPTRYCONVMARGINAL2) ) ){
7411  break;
7412  }
7413 #endif
7414 
7415  }// end if finite
7416 
7417 
7418 
7419 
7420 
7421 
7423  //
7424  // revert any back-ups if ok to do so
7425  //
7426  // NOTEMARK: Can only modify uu0 or frac's after they are used consistently to get f1, iJ, take step, and check convergence with error function
7427  //
7429  changeotherdt=1;
7431  // if(fracuup!=1.0){
7432  // if(fabs(fracuup-1.0)>10.0*NUMEPSILON){
7433  if(fracuup<1.0){
7434  // try increasing amount of uu or pp used
7435  fracuup*=RADDAMPUNDELTA;
7436  fracuup=MIN(1.0,fracuup);
7437  changeotherdt=0; // ensure fracuup back to 1.0 first before reverting others.
7438  }
7440  // if(fracdtuu0!=1.0){
7441  // if(fabs(fracdtuu0-1.0)>10.0*NUMEPSILON && changeotherdt){
7442  if(fracdtuu0<1.0 && changeotherdt){
7443  // try increasing uu0 away from Uiin to account for full dUother
7444  fracdtuu0*=RADDAMPUNDELTA;
7445  fracdtuu0=MIN(1.0,fracdtuu0);
7446  // FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
7447  PLOOP(pliter,pl) uu0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall); // modifies uu0
7448  {
7449  FTYPE uuiterback[NPR];
7450  PLOOP(pliter,pl) uuiterback[pl] = uu[pl]; // hold actual iterated quantities
7451  PLOOP(pliter,pl) uu[pl] = uu0[pl]; // "iterate" non-iterated quantities
7452  JACLOOP(ii,ru.startjac,ru.endjac) uu[ru.irefU[ii]] = uuiterback[ru.irefU[ii]]; // overwrite with actual previous step for iterated quantities
7453  }
7454  // KORALNOTE: No need to get pp0, since never used. uu0 only used in error function.
7455  }
7457  // if(fracdtG!=1.0){
7458  // if(fabs(fracdtG-1.0)>10.0*NUMEPSILON && changeotherdt){
7459  if(fracdtG<1.0 && changeotherdt){
7460  // try increasing amount of G applied
7461  fracdtG*=RADDAMPUNDELTA;
7462  fracdtG=MIN(1.0,fracdtG);
7463  }
7464 
7465 
7467  // see if took too many Newton steps or not finite results
7469  *nummhdstepsreturn = (int)(nstroke-nstrokeorig); // get number of mhd inversion steps
7470  if(iter>trueimpmaxiter || *nummhdstepsreturn>MAXMHDSTEPS || notfinite ){
7471  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"iter=%d>%d mhdsteps=%d>%d or notfinite=%d\n",iter,trueimpmaxiter,*nummhdstepsreturn,MAXMHDSTEPS,notfinite);
7472  // failreturn=FAILRETURNGENERAL; // no don't fail, might be allowable error.
7473  break;
7474  }
7475 
7476  }// end do
7477  while(1);
7478 
7479 
7480 
7481 
7482 
7483 
7484 
7485 
7487  //
7488  // once done iterating, regardless of result or failure, need to ensure non-iterated quantities are normal
7489  //
7491  fracdtuu0=1.0;
7492  //
7493  // FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
7494  PLOOP(pliter,pl) uu0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall); // modifies uu0
7495  PLOOP(pliter,pl){
7496  if(!(pl>=UU && pl<=U3 || RADPL(pl) || pl==ENTROPY)){
7497  uu[pl] = uu0[pl];
7498  }
7499  }
7500  // regardless, invert non-iterated quantities
7501  // 1) trivially invert field
7502  PLOOPBONLY(pl) bestpp[pl]=bestuu[pl]=pp[pl] = uu0[pl];
7503  // 2) trivially invert to get rho assuming q up-to-date
7504  // pp[RHO]= uu0[RHO]/q->ucon[TT]; // q might not be up-to-date
7505  // 3) Invert other scalars (only uses uu[RHO], not pp[RHO])
7506  extern int invert_scalars1(struct of_geom *ptrgeom, FTYPE *Ugeomfree, FTYPE *pr);
7507  invert_scalars1(ptrgeom, uu,pp);
7508  extern int invert_scalars2(struct of_geom *ptrgeom, FTYPE *Ugeomfree, struct of_state *q, FTYPE *pr);
7509  invert_scalars2(ptrgeom, uu, q, pp);
7510  PLOOP(pliter,pl){
7511  if(SCALARPL(pl)){
7512  bestpp[pl]=pp[pl];
7513  bestuu[pl]=uu[pl];
7514  }
7515  }
7516  //
7517  // end trivial inversion
7518  //
7520 
7521 
7522 
7523 
7525  //
7526  // if no failure, then see if really still failed or not with some final checks.
7527  //
7529  int failreturnf=0;
7530  // if(failreturn==0 && (earlylowerror==0 && lowitererror==0) ){
7531  if(failreturn==0 && earlylowerror==0){ // still check if lowitererror==1 because might have best total error at another iter.
7532 
7533 
7534  // if didn't fail, shouldn't need to set fracdtuu0=1, but do so just in caes.
7535  fracdtuu0=1.0;
7536 
7537 
7538  int fakeiter;
7539  for(fakeiter=0;fakeiter<=0;fakeiter++){
7540 
7541  int convreturn=1,convreturnok=1,convreturnallow=1; // default is solution is acceptable.
7542 
7543 
7544  if(DOFINALCHECK){
7546  //
7547  // check and get error for last iteration or any mods from above that are post-iteration
7548  //
7549  // uses final uu0 with fracdtuu0=1 to ensure really updated non-iterated quantities correctly
7550  //
7551  // The call to f_implicit() also ensures uu is consistent with new pp
7552  //
7554  int whichcall=FIMPLICITCALLTYPEFINALCHECK;
7555  // eomtypelocal=*eomtype; // re-chose default each time. No, stick with what f1 (last call to f1) chose
7556  int goexplicitfake; // not used here
7557  int dimtypef=DIMTYPEFCONS; // 0 = conserved R^t_\nu type, 1 = primitive (u,v^i) type, i.e. v^i has no energy density term
7558  int fakef1iter=-1;
7559  failreturnf=f_implicit(allowbaseitermethodswitch, iter,fakef1iter,failreturnallowableuse, whichcall,impepsjac,showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, baseitermethod, fracenergy, dissmeasure, radinvmod, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, pp, pp, piin, uu, Uiin, uu0, uu, fracdtG*realdt, ptrgeom, q, f1, f1norm, f1report, &goexplicitfake, &errorabsf1[0], &errorabsf1[1], WHICHERROR, &convreturn, nummhdinvsreturn, &tautotmaxreturn, &mtd, &ru); // modifies uu and pp and q and f1report and goexplicitfake and errorabsf1
7560  // radinvmod contains whether radiative inversion modified process.
7561 
7562  // convreturn=f_error_check(showmessages, showmessagesheavy, iter, trueimptryconv,trueimptryconvabs,realdt,dimtypef,eomtypelocal,*radinvmod, itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,pp,piin,f1,f1norm,f1report,Uiin,uu0,uu,ptrgeom,&errorabsf1,WHICHERROR,&mtd,&ru);
7563  convreturnallow=(errorabsf1[WHICHERROR]<trueimpallowconvabs);
7564  convreturnok=(errorabsf1[WHICHERROR]<trueimpokconvabs);
7565  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"DOFINALCHECK: convreturn=%d convreturnok=%d convreturnallow=%d (IMPOKCONV=%g IMPALLOWCONV=%g) f1report: %g %g %g %g : %g %g\n",convreturn,convreturnok,convreturnallow,IMPOKCONV,IMPALLOWCONV,f1report[ru.erefU[0]],f1report[ru.erefU[1]],f1report[ru.erefU[2]],f1report[ru.erefU[3]],errorabsf1[0],errorabsf1[1]);
7566  }// end if doing final check
7567  else{
7568  // kinda risky to rely upon last step but not checking its error
7569 
7570  if(IMPPTYPE(mtd.implicititer)){
7571  // since iterated pp or uu but didn't call f_implicit(), uu or pp (respectively) is no longer consistent.
7572  // So get uu(pp)
7573  struct of_state qcons;
7574  get_state(pp, ptrgeom, &qcons);
7575  primtoU(UNOTHING,pp,&qcons,ptrgeom, uu, NULL);
7576  }
7577 
7578  // now get error
7579  int dimtypef=DIMTYPEFCONS; // 0 = conserved R^t_\nu type, 1 = primitive (u,v^i) type, i.e. v^i has no energy density term
7580  convreturn=f_error_check(showmessages, showmessagesheavy, iter, trueimptryconv, trueimptryconvabs,realdt,dimtypef,eomtypelocal,*radinvmod,itermode,*baseitermethod,fracenergy,dissmeasure,dimfactU,pp,piin,f1,f1norm,f1report,Uiin,uu0,uu,ptrgeom,&errorabsf1[0],&errorabsf1[1],WHICHERROR,&mtd,&ru);
7581  convreturnallow=(errorabsf1[WHICHERROR]<trueimpallowconvabs);
7582  convreturnok=(errorabsf1[WHICHERROR]<trueimpokconvabs);
7583  }
7584 
7585 
7586 
7587  if(GETBEST){
7588 
7589  if(gotbest){
7590  // f1-based
7591  // using old uu,uup, but probably ok since just helps normalize error
7592  errorabsf1[0]=0.0; JACLOOPFULLERROR(itermode,jj,ru.startjac,ru.endjac) errorabsf1[0] += fabs(f1report[ru.erefU[jj]]);
7593  errorabsf1[1]=0.0; JACLOOPSUPERFULL(pliter,pl,eomtypelocal,*baseitermethod,*radinvmod) errorabsf1[1] += fabs(f1report[pl]);
7594  errorabsbest[0]=0.0; JACLOOPFULLERROR(itermode,jj,ru.startjac,ru.endjac) errorabsbest[0] += fabs(lowestf1report[ru.erefU[jj]]);
7595  errorabsbest[1]=0.0; JACLOOPSUPERFULL(pliter,pl,eomtypelocal,*baseitermethod,*radinvmod) errorabsbest[1] += fabs(lowestf1report[pl]);
7596 
7597  // see if should revert to prior best
7598  if(errorabsbest[WHICHERROR]<errorabsf1[WHICHERROR] || !isfinite(errorabsf1[WHICHERROR]) ){
7599  if(showmessages && debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"Using best: %g %g : %g %g\n",errorabsf1[0],errorabsf1[1],errorabsbest[0],errorabsbest[1]);
7600 
7601  PLOOP(pliter,pl) uu[pl]=bestuu[pl];
7602  PLOOP(pliter,pl) pp[pl]=bestpp[pl];
7603  errorabsf1[0]=errorabsbest[0];
7604  errorabsf1[1]=errorabsbest[1];
7605  PLOOP(pliter,pl) f1[pl] = lowestf1[pl];
7606  PLOOP(pliter,pl) f1norm[pl] = lowestf1norm[pl];
7607  PLOOP(pliter,pl) f1report[pl] = lowestf1report[pl];
7608  *radinvmod = radinvmodbest;
7609 
7610  // get whether converged
7611  convreturn=(errorabsf1[WHICHERROR]<trueimptryconvabs);
7612  convreturnallow=(errorabsf1[WHICHERROR]<trueimpallowconvabs);
7613  convreturnok=(errorabsf1[WHICHERROR]<trueimpokconvabs);
7614  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"GETBEST: convreturn=%d convreturnok=%d convreturnallow=%d (IMPOKCONV=%g IMPALLOWCONV=%g) f1report: %g %g %g %g : %g %g\n",convreturn,convreturnok,convreturnallow,IMPOKCONV,IMPALLOWCONV,f1report[ru.erefU[0]],f1report[ru.erefU[1]],f1report[ru.erefU[2]],f1report[ru.erefU[3]],errorabsf1[0],errorabsf1[1]);
7615  }
7616  else{
7617  if(debugfail>=DEBUGLEVELIMPSOLVERMORE) dualfprintf(fail_file,"gotbest=%d but errorabsbest=%g %g while errorabsf1=%g %g\n",gotbest,errorabsbest[0],errorabsbest[1],errorabsf1[0],errorabsf1[1]);
7618  PLOOP(pliter,pl) bestuu[pl]=uu[pl];
7619  PLOOP(pliter,pl) bestpp[pl]=pp[pl];
7620  errorabsbest[0]=errorabsf1[0];
7621  errorabsbest[1]=errorabsf1[1];
7622  radinvmodbest = *radinvmod;
7623  failreturnbest = failreturn;
7624  }
7625  }
7626  }// end GETBEST
7627 
7628 
7629 
7630 
7631 
7632 
7633 
7634 
7635 
7636 
7637 
7638 
7639  // KORALTODO: If convreturnallow doesn't work, but still (say) 10% error, might want to hold onto result in case explicit backup fails as well (which is likely), in which case *much* better to use 10% error because otherwise 4-force not accounted for, which can lead to very big changes in fluid behavior due to large flux from previous step.
7640  // KORALTODO: Or, perhaps should really take it as a failure and use fixups. Probably should allow for result to be written if error<10%, but only use as super-backup in fixups. So should set pflag still.
7641 
7643  //
7644  // See if reached desired tolerance
7645  //
7647  if(convreturn || convreturnok){
7648  // then really done
7649  failreturn=FAILRETURNNOFAIL; mathfailtype=0;
7650  break;
7651  }
7652  else{ // convreturn==0 && convreturnok==0
7653 
7654  // see if at least allowed error
7655  if(convreturnallow){
7656 
7657  // set as soft allowable failure
7658  failreturn=FAILRETURNNOTTOLERROR; mathfailtype=202;
7659 
7660  if(iter>trueimpmaxiter){// then reached maximum iterations
7661  prod0dualfprintf(debugfail>=2,fail_file,"trueimpmaxiter=%d eomtype=%d MAXcheckconv=%d havebackup=%d failreturnallowable=%d: f1report=%g %g %g %g : f1=%g %g %g %g\n",trueimpmaxiter,eomtypelocal,checkconv,havebackup,failreturnallowable,f1report[ru.erefU[0]],f1report[ru.erefU[1]],f1report[ru.erefU[2]],f1report[ru.erefU[3]],f1[ru.erefU[0]],f1[ru.erefU[1]],f1[ru.erefU[2]],f1[ru.erefU[3]]);
7662 
7663  prod0dualfprintf(showmessages && debugfail>=2,fail_file,"iter>trueimpmaxiter=%d : iter exceeded in solve_implicit_lab(). But f1 was allowed error. checkconv=%d (if checkconv=0, could be issue!) : %g %g %g %g : %g %g %g %g : errorabs=%g %g : %g %g %g\n",trueimpmaxiter,checkconv,f1report[ru.erefU[0]],f1report[ru.erefU[1]],f1report[ru.erefU[2]],f1report[ru.erefU[3]],f1[ru.erefU[0]],f1[ru.erefU[1]],f1[ru.erefU[2]],f1[ru.erefU[3]],errorabsf1[0],errorabsf1[1],fracdtuu0,fracuup,fracdtG);
7665  if(havebackup){
7666  prod0dualfprintf(debugfail>=DEBUGLEVELIMPSOLVERMORE,fail_file,"SWITCHING MODE: Detected MAXITER\n");
7667  // don't break, just reporting or not
7668  mathfailtype=50;
7669  }
7670  else{
7671  mathfailtype=(eomtypelocal==EOMGRMHD ? 6 : 600);
7672  }
7673  }
7674  }
7675 
7676  // then nothing else to do
7677  break;
7678  }
7679  else{ // didn't reach allowable error
7680  // not allowable failure
7681  failreturn=FAILRETURNGENERAL; mathfailtype=203;
7682 
7683 
7684 #if(PRODUCTION==0)
7685  // KORALTODO: Need backup that won't fail.
7686  if(debugfail>=2){
7687  if(canbreak==1 && havebackup==0) dualfprintf(fail_file,"Held u_g, couldn't hold anymore and broke, but error still larger than allowed : iter=%d ijknstepsteppart=%d %d %d %ld %d\n",iter,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
7688  if(canbreak==2 && havebackup==0) dualfprintf(fail_file,"Aborted due to oscillatory error despite not having backup: iter=%d\n",iter);
7689  if(canbreak==3 && havebackup==0) dualfprintf(fail_file,"Aborted due to error not decreasing fast enough: iter=%d errorabsf1=%g %g\n",iter,errorabsf1[0],errorabsf1[1]);
7690  if(canbreak==4 && havebackup==0) dualfprintf(fail_file,"Aborted due to error not decreasing fast enough: iter=%d errorabsf1=%g %g\n",iter,errorabsf1[0],errorabsf1[1]);
7691  if(canbreak==5 && havebackup==0) dualfprintf(fail_file,"Aborted due to error not decreasing fast enough: iter=%d errorabsf1=%g %g\n",iter,errorabsf1[0],errorabsf1[1]);
7692  if(iter>trueimpmaxiter && havebackup==0) dualfprintf(fail_file,"iter>trueimpmaxiter=%d : iter exceeded in solve_implicit_lab(). nstep=%ld steppart=%d ijk=%d %d %d : Bad error.\n",trueimpmaxiter,nstep,steppart,ptrgeom->i,ptrgeom->j,ptrgeom->k);
7693  if(notfinite && havebackup==0) dualfprintf(fail_file,"IMPGOTNAN at iter=%d : in solve_implicit_lab(). ijk=%d %d %d : Bad error.\n",iter,ptrgeom->i,ptrgeom->j,ptrgeom->k);
7694  if(havebackup==0) dualfprintf(fail_file,"checkconv=%d havebackup=%d failreturnallowable=%d: f1report=%g %g %g %g : f1=%g %g %g %g\n",checkconv,havebackup,failreturnallowable,f1report[ru.erefU[0]],f1report[ru.erefU[1]],f1report[ru.erefU[2]],f1report[ru.erefU[3]],f1[ru.erefU[0]],f1[ru.erefU[1]],f1[ru.erefU[2]],f1[ru.erefU[3]]);
7695  if(1||showmessages){
7696  if(havebackup){
7697  // don't break, just don't report.
7698 
7699  mathfailtype=60;
7700  }
7701  else{
7702  mathfailtype=1;
7703  }
7704  }
7705 
7706  }// debug
7707 #endif
7708 
7709  // nothing else to do except leave
7710  break;
7711  }// end if convreturnallow=0 (didn't reach allowed error)
7712  }// end if didn't reach desired error
7713 
7714 
7715 
7716 
7717 
7718  }// end fake loop that can break out of
7719  }// end if failreturn==0 originally
7720 
7721 
7722  // get best failreturn
7723  if(GETBEST){
7724  if(gotbest){
7725  failreturnbest=failreturn;
7726  radinvmodbest = *radinvmod;
7727  }
7728  }
7729 
7730 
7731  // estimate effective work based on iterations done for each equation type
7732  FTYPE fndim=(FTYPE)NDIM;
7733  totaliters += (int)( (3.0/fndim)*(FTYPE)momiters + (1.0/fndim)*(FTYPE)energyiters + (fndim/fndim)*(FTYPE)fulliters);
7734 
7735  }// end loop over damping
7736  if(dampattempt==truenumdampattempts && truenumdampattempts>1){
7737  prod0dualfprintf(debugfail>=2,fail_file,"Damping failed to avoid max iterations (but error might have dropped: %21.15g %21.15g): failreturn=%d dampattempt=%d eomtypelocal=%d eomtypelocal=%d ijk=%d %d %d\n",errorabsf1[0],errorabsf1[1],failreturn,dampattempt,eomtypelocal,eomtypelocal,ptrgeom->i,ptrgeom->j,ptrgeom->k);
7738  }
7739 
7740 
7741  }// end explicitattempt
7742 
7743 
7744 
7745 
7746 
7747 
7748 
7750  //
7751  // Once damping or explicitattemps are done, ensure choose best over all tries
7752  //
7754  if(GETBEST){
7755  if(gotbest){
7756  PLOOP(pliter,pl) uu[pl]=bestuu[pl];
7757  PLOOP(pliter,pl) pp[pl]=bestpp[pl];
7758  errorabsf1[0]=errorabsbest[0];
7759  errorabsf1[1]=errorabsbest[1];
7760  failreturn=failreturnbest;
7761  *radinvmod = radinvmodbest;
7762  }
7763  }
7764 
7765 
7766 
7767 
7768  if(ACTUALHARDFAILURE(failreturn)==0){ // deal with radinv issue but only if didn't fail
7769 
7771  //
7772  // But, in general, for QTYPMHD methods, might have use CAPTYPEFIX2 or CAPTYPEFIX1, but should use whichcap (probably CAPTYPEBASIC) to be conservative on value of Erf in general. So while converged", could have avoided URAD0 error in total error for QTYPMHD methods. So recover whichcap result before moving onto setting dUcomp.
7773  //
7775  if(RADINVBAD(*radinvmod) && IMPMHDTYPEBASE(*baseitermethod)==1){
7776  int whichcall=FIMPLICITCALLTYPEFINALCHECK2; // KEY CHOICE IS THIS, which will use whichcap
7777  int goexplicitfake;
7778  int dimtypef=DIMTYPEFCONS; // 0 = conserved R^t_\nu type, 1 = primitive (u,v^i) type, i.e. v^i has no energy density term
7779  int fakef1iter=-1;
7780  FTYPE fakefracdtG=1.0;
7781  FTYPE f1fake[NPR],f1normfake[NPR],f1reportfake[NPR];
7782  FTYPE errorabsf1fake[NUMERRORTYPES];
7783  errorabsf1fake[0]=errorabsf1[0];
7784  errorabsf1fake[1]=errorabsf1[1];
7785  int convreturnfake=1;
7786  FTYPE fakeimpepsjac=1E-6;
7787  int fakefailreturnf=f_implicit(allowbaseitermethodswitch, iter,fakef1iter,failreturnallowableuse, whichcall,fakeimpepsjac,showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, baseitermethod, fracenergy, dissmeasure, radinvmod, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, pp, pp, piin, uu, Uiin, uu0, uu, fakefracdtG*realdt, ptrgeom, q, f1fake, f1normfake, f1reportfake, &goexplicitfake, &errorabsf1fake[0], &errorabsf1fake[1], WHICHERROR, &convreturnfake, nummhdinvsreturn, &tautotmaxreturn, &mtd, &ru);
7788  // ONLY modifies uu and pp and q using true whichcap
7789  // *and* radinvmod, which contains whether radiative inversion modified solution.
7790  }
7791 
7793  //
7794  // In general, uu might still not be uu=uu(pp) because might have used uualt in f_implicit()
7795  // But now that done with determining which solution we want to use with what error, now make consistent.
7796  // This needs to come *before* radsource or dUcomp is computed using uu, because uualt was only for error and not actual value that we want to fix-up to no longer require uualt in sense of making U change enough to be like primitive p.
7797  //
7799  if(ALLOWUSEUUALT){
7800  get_state(pp, ptrgeom, q);
7801  primtoU(UNOTHING,pp,q,ptrgeom, uu, NULL);
7802  }
7803 
7804 
7805  if(0){ // no longer do this since do above full primtoU
7807  //
7808  // have to compute final uu[ENTROPY] if doing entropy optimization where avoid it during iterations if not needed.
7809  //
7811  if(ENTROPYOPT){
7812  int needentropy=1;
7813  get_state_norad_part2(needentropy, pp, ptrgeom, q); // where entropy would be computed
7814  // get_state(pp, ptrgeom, q);
7815  extern int primtoflux_nonradonly(int needentropy, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
7816  FTYPE uuentropy[NPR];
7817  primtoflux_nonradonly(needentropy,pp,q,TT,ptrgeom, uuentropy, NULL);
7818  uu[ENTROPY]=uuentropy[ENTROPY];
7819  }
7820  }
7821 
7822  }
7823 
7825  //
7826  // try to obtain total energy conservation *with* entropy solution for gas by borrowing from radiation.
7827  // Do this by trying to keep entropy version of gas variables that have good enough total solution
7828  //
7830  if(BORROWENTROPY && ACCEPTASNOFAILURE(failreturn)==1 && eomtypelocal==EOMENTROPYGRMHD){
7831 
7832  // set borrow version of uu
7833  FTYPE uuborrow[NPR];
7834  FTYPE ppborrow[NPR];
7835  struct of_state qborrowdontuse;
7836  struct of_state *qborrow=&qborrowdontuse;
7837  PLOOP(pliter,pl) uuborrow[pl] = uu[pl];
7838  PLOOP(pliter,pl) ppborrow[pl] = pp[pl];
7839  *qborrow=*q;
7840 
7841  // energy added to gas
7842  FTYPE dugas=uuborrow[UU]-uu0[UU];
7843  // try enforcing energy conservation
7844  uuborrow[URAD0] = uu0[URAD0] - dugas;
7845 
7846 
7847  // invert full solution with errors
7848  int whichcall=FIMPLICITCALLTYPEFINALCHECK2; // KEY CHOICE IS THIS, which will use whichcap
7849  int goexplicitborrow;
7850  int dimtypef=DIMTYPEFCONS; // 0 = conserved R^t_\nu type, 1 = primitive (u,v^i) type, i.e. v^i has no energy density term
7851  int borrowf1iter=-1;
7852  FTYPE borrowfracdtG=1.0;
7853  FTYPE f1borrow[NPR],f1normborrow[NPR],f1reportborrow[NPR];
7854  FTYPE errorabsf1borrow[NUMERRORTYPES];
7855  errorabsf1borrow[0]=errorabsf1[0];
7856  errorabsf1borrow[1]=errorabsf1[1];
7857  int convreturnborrow=1;
7858  FTYPE borrowimpepsjac=1E-6;
7859  int radinvmodborrow=0;
7860  int borrowfailreturnf=f_implicit(allowbaseitermethodswitch, iter,borrowf1iter,failreturnallowableuse, whichcall,borrowimpepsjac,showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, baseitermethod, fracenergy, dissmeasure, &radinvmodborrow, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, ppborrow, ppborrow, piin, uuborrow, Uiin, uu0, uuborrow, borrowfracdtG*realdt, ptrgeom, qborrow, f1borrow, f1normborrow, f1reportborrow, &goexplicitborrow, &errorabsf1borrow[0], &errorabsf1borrow[1], WHICHERROR, &convreturnborrow, nummhdinvsreturn, &tautotmaxreturn, &mtd, &ru);
7861 
7862  if(ALLOWUSEUUALT){
7863  get_state(pp, ptrgeom, q);
7864  primtoU(UNOTHING,pp,q,ptrgeom, uu, NULL);
7865  }
7866 
7867 #define BORROWTOL (1E-1)
7868 
7869  // only borrow if error is not order unity and if was and is plenty of energy in radiation to give
7870  // e.g., borrowing from radiation can leave radiation hitting floor, do not improving total energy conservation in such cases.
7871  // or allow shift in radiation energy if only adding energy to radiation
7872  // if(errorabsf1borrow[WHICHERROR]<BORROWTOL && ((-uuborrow[URAD0])>(-uuborrow[UU])) ){}
7873  // if(errorabsf1borrow[WHICHERROR]<BORROWTOL && ((-uuborrow[URAD0])>(-dugas) || (-dugas<0.0)) ){
7874  if(radinvmodborrow==UTOPRIMRADNOFAIL && errorabsf1borrow[WHICHERROR]<BORROWTOL && ((-uuborrow[URAD0])>(-dugas) || (-dugas<0.0)) ){
7875  // then use new solution regardless of how it is correct 4-force, just so energy-momentum can be conserved
7876  // if randinvmodborrow!=0, then not enough radiation energy to give, and would violate energy-momentum conservation anyways, so wait till very end for consfixup_1zone() to fixup things if it can
7877  PLOOP(pliter,pl){
7878  uu[pl] = uuborrow[pl];
7879  pp[pl] = ppborrow[pl];
7880  }
7881  errorabsf1[0]=errorabsf1borrow[0];
7882  errorabsf1[1]=errorabsf1borrow[1];
7883 #if(PRODUCTION==0&&0)
7884  prod0dualfprintf(1,fail_file,"YESSwitched: %g : uu=%g %g : dugas=%g\n",errorabsf1borrow[WHICHERROR],-uuborrow[URAD0],-uuborrow[UU],-dugas);
7885 #endif
7886  }
7887  else{
7888  // if not good idea to borrow, still update uu as if did. Might be able to recover if this is just sub-step being added to bigger step. Plus, only use uu from here on as diagnostic if implicit solver obtained full solution to primitive inversion (as normal for most RK methods).
7889  PLOOP(pliter,pl){
7890  uu[pl] = uuborrow[pl]; // ensures full energy conservation even when entropy method used. Or at least, diagnostic will have non-conservation part in "fl"
7891  }
7892 
7893 #if(PRODUCTION==0&&0)
7894  prod0dualfprintf(1,fail_file,"NOSwitched: %g : uu=%g %g dugas=%g\n",errorabsf1borrow[WHICHERROR],-uuborrow[URAD0],-uuborrow[UU],dugas);
7895 #endif
7896  }
7897 
7898 
7899  }// end if borrowing entropy/energy from radiation to give to gas
7900 
7901 
7902 
7904  //
7905  // in case radinvmod==1 or no solution, force conservation so at least "fl" diagnostic works.
7906  //
7908  if(IMPMHDTYPEBASE(*baseitermethod)==1){
7909  FTYPE dugas[4];
7910  DLOOPA(jj) dugas[jj] = uu[UU+jj]-uu0[UU+jj];
7911  DLOOPA(jj) uu[URAD0+jj] = uu0[URAD0+jj] - dugas[jj];
7912  }
7913  else{// IMPRADTYPEBASE(*baseitermethod)
7914  FTYPE durad[4];
7915  DLOOPA(jj) durad[jj] = uu[URAD0+jj]-uu0[URAD0+jj];
7916  DLOOPA(jj) uu[UU+jj] = uu0[UU+jj] - durad[jj];
7917  }
7918 
7919 
7921  // ensure if failed that no changes in quantities
7923  if(ACCEPTASNOFAILURE(failreturn)==0){
7924  DLOOPA(jj) uu[UU+jj] = uu0[UU+jj];
7925  DLOOPA(jj) uu[URAD0+jj] = uu0[URAD0+jj];
7926  if(ENTROPY>=0) uu[ENTROPY] = uu0[ENTROPY];
7927  }
7929  // if cold method, then entropy change infinite. Modify so no change in entropy. Ok, because not using entropy conservation here. Just need evolution of entropy to be reasonable in case revert to it, and also want ener diagnostics to be reasonable and show conservation properties of entropy.
7930  // constant uu[ENTROPY] consistent with eventually averaging internal energy to get close to original internal energy (i.e. rather than formally zero).
7932  if(*eomtype==EOMCOLDGRMHD){
7933  if(ENTROPY>=0) uu[ENTROPY]=uu0[ENTROPY];
7934  }
7935 
7936 
7937 
7939  //
7940  // if didn't fail to get some reasonable solution, then now can use it.
7941  //
7943  if(ACCEPTASNOFAILURE(failreturn)==1){
7944 
7946  //
7947  // get source update as "dU" = dU/dt using real dt that used during implicit iterations, and will eventually use to update U in advance.c.
7948  // apply source update as force
7949  // KORALNOTE: As long as f_implicit() updates both full primitive and full U, using uu below is fine and good.
7950  PLOOP(pliter,pl) radsource[pl] = +(uu[pl]-uu0[pl])/realdt;
7951  // KORALNOTE: Could re-enforce energy conservation here, but would be inconsistenet with how applied error function.
7952  PLOOPBONLY(pl) radsource[pl] = 0.0; // force to machine accuracy
7953 
7954 
7955  // DLOOPA(ii) radsource[ru.iotherU[ii]] = -radsource[ru.erefU[ii]]; // force energy conservation (NOTEMARK: Unsure if optimal since loop iterates and might break this for good reason -- e.g. no exactly valid corresponding MHD solution if iterating URAD)
7956 
7957 
7958  // OLD, but misses rho changes due to u^t changes:
7959  // DLOOPA(jj) radsource[ru.iotherU[jj]] = -(uu[ru.irefU[jj]]-uu0[ru.irefU[jj]])/realdt;
7960  // DLOOPA(jj) radsource[ru.irefU[jj]] = +(uu[ru.irefU[jj]]-uu0[ru.irefU[jj]])/realdt;
7961 
7962 
7963  // DEBUG:
7964  // DLOOPA(jj) dualfprintf(fail_file,"nstep=%ld steppart=%d i=%d implicitGd[%d]=%g %g\n",nstep,steppart,ptrgeom->i,jj,radsource[ru.iotherU[jj]],radsource[ru.irefU[jj]]);
7965 
7966 
7968  //
7969  // store source update in dUcomp for return.
7970  //
7972  sc = RADSOURCE;
7973  PLOOP(pliter,pl) dUcomp[sc][pl] += radsource[pl];
7974 
7976  //
7977  // save better guess for later inversion from this inversion
7978  // pp was modified by f_implicit(f1,pp) with output from inversion returned through pp0
7979  // only use pp if successful with implicit method, since if not successful can be various bad reasons with no good pb
7980  //
7982  PLOOP(pliter,pl){
7983  pb[pl]=pp[pl]; // actual solution that's used
7984  uub[pl]=uu[pl]; // used for getting whether solution really worked and switching methods, etc.
7985  }
7986 
7987  // DEBUG:
7988  // PLOOP(pliter,pl) dualfprintf(fail_file,"POOP2: pl=%d uu=%21.15g uu0=%21.15g piin=%21.15g pb=%21.15g\n",pl,uu[pl],uu0[pl],piin[pl],pb[pl]);
7989 
7991  //
7992  // choose new eomtype for external inverison or other checks
7993  //
7994  // This ensures whatever implicit solver settled on using, the external inversion doesn't switch.
7995  //
7997  *eomtype=eomtypelocal;
7998 
7999 
8000 
8001  if(SWITCHTODONOTHING){
8002  // always do nothing, so entropy won't try to revert to cold.
8003  if(*eomtype==EOMENTROPYGRMHD) *eomtype=EOMDIDENTROPYGRMHD;
8004  if(*eomtype==EOMCOLDGRMHD) *eomtype=EOMDIDCOLDGRMHD;
8005  if(*eomtype==EOMGRMHD) *eomtype=EOMDIDGRMHD;
8006  }
8007 
8008  }// end if didn't fail, so can set final solution.
8009 
8010 
8011 
8012 
8013 
8014 
8015 
8017  //
8018  // Return error and iterations and fail mode
8019  //
8021 
8022  // report error no matter whether got solution or not.
8023  errorabsreturn[0]=errorabsf1[0];
8024  errorabsreturn[1]=errorabsf1[1];
8025 
8026  // report iters not matter what the error.
8027  *itersreturn=totaliters;
8028 
8029  *nummhdstepsreturn = (int)(nstroke-nstrokeorig); // get number of mhd inversion steps
8030 
8031 
8032 
8033 
8034  // check if uncaught nan/inf
8035  int caughtnan=0;
8036  PLOOPDYNAMICAL(pliter,pl){
8037  if(!isfinite(pb[pl])) caughtnan++;
8038  if(!isfinite(uub[pl])) caughtnan++;
8039  if(!isfinite(dUcomp[RADSOURCE][pl])) caughtnan++;
8040  }
8041  if(!isfinite(errorabsreturn[0])) caughtnan++;
8042  if(!isfinite(errorabsreturn[1])) caughtnan++;
8043 
8044  if(caughtnan){
8045  // this doesn't seem to be hit even on Kraken
8046  if(debugfail>=2){
8047  dualfprintf(fail_file,"per mode implicit solver generated nan result and it wasn't caught\n");
8048  dualfprintf(fail_file,"per mode implicit solver: %d %d %d %d %d %d %d %d : %g %g %g : %d %d : %g %g : %d\n",allowbaseitermethodswitch, modprim, havebackup, didentropyalready, *eomtype, whichcap, itermode, *baseitermethod, trueimptryconv, trueimpokconv, trueimpallowconv, trueimpmaxiter, truenumdampattempts, fracenergy, dissmeasure, *radinvmod);
8049  PLOOPDYNAMICAL(pliter,pl) dualfprintf(fail_file,"0implicit solver: pl=%d Uiin=%21.15g dUother=%21.15g dU=%21.15g\n",pl,Uiin[pl],dUother[pl],dUcomp[RADSOURCE][pl]);
8050  PLOOPDYNAMICAL(pliter,pl) dualfprintf(fail_file,"1implicit solver: pl=%d pb=%21.15g piin=%21.15g Ufin=%21.15g dU=%21.15g uub=%21.15g\n",pl,pb[pl],piin[pl],Ufin[pl],dUcomp[RADSOURCE][pl],uub[pl]);
8051  int jjj;
8052  DLOOPA(jjj) dualfprintf(fail_file,"2implicit solver: jj=%d ucon=%21.15g ucov=%21.15g uradcon=%21.15g uradcov=%21.15g\n",jj,q->ucon[jj],q->ucov[jj],q->uradcon[jj],q->uradcov[jj]);
8053  }
8054  // reset solution as bad error, so conditions don't get confused by nan always giving false
8055  errorabsreturn[0]=1.0;
8056  errorabsreturn[1]=1.0;
8057 
8058  failreturn=FAILRETURNGENERAL;
8059  }
8060 
8061 
8062 
8064  //
8065  // report any bad failure (using previously set mathfailtype value)
8066  //
8068 
8069  // for checking cases where tau>=1 but still Erf<0
8070  // FTYPE tautot[NDIM],tautotmax;
8071  // calc_tautot(pp, ptrgeom, q, tautot, &tautotmax);
8072  // // if(tautotmax>1 && pp[PRAD0]<10.0*ERADLIMIT){
8073  // if(tautotmax>2 && pp[PRAD0]<10.0*ERADLIMIT){
8074 
8075 
8076  if(PRODUCTION==0 && NOTACTUALFAILURE(failreturn)==0 && errorabsf1[WHICHERROR]>=trueimptryconvalt || PRODUCTION==0 && NOTBADFAILURE(failreturn)==0 && havebackup==0){ // as in previous code
8077 
8078  PLOOP(pliter,pl) dualfprintf(fail_file,"ERRORCHECK: pl=%d f1=%21.15g f1norm=%21.15g f1report=%21.15g errorabsf1=%21.15g errorallabsf1=%21.15g\n",pl,f1[pl],f1norm[pl],f1report[pl],errorabsf1[0],errorabsf1[1]);
8079 
8080 
8081 
8082  // for seeing Erf<0 and small errors not tol errors.
8083  // if(failreturn!=FAILRETURNMODESWITCH && (pp[PRAD0]<10.0*ERADLIMIT) || PRODUCTION==0 && NOTACTUALFAILURE(failreturn)==0 && errorabsf1[WHICHERROR]>=trueimptryconvalt || PRODUCTION>0 && NOTBADFAILURE(failreturn)==0 && havebackup==0){
8084 
8085  // for catching oscillators at small error but still >tol.
8086  // if(PRODUCTION==0 && NOTACTUALFAILURE(failreturn)==0 || PRODUCTION>0 && NOTBADFAILURE(failreturn)==0){
8087 
8088 
8089  // if(REPORTERFNEG && failreturn!=FAILRETURNMODESWITCH && (pp[PRAD0]<10.0*ERADLIMIT || RADINVBAD(*radinvmod) ) || PRODUCTION==0 && NOTACTUALFAILURE(failreturn)==0 && errorabsf1[WHICHERROR]>=trueimptryconvalt || PRODUCTION>0 && NOTBADFAILURE(failreturn)==0 && havebackup==0){
8090  // if(REPORTERFNEG && failreturn!=FAILRETURNMODESWITCH && (pp[PRAD0]<10.0*ERADLIMIT) || PRODUCTION==0 && NOTACTUALFAILURE(failreturn)==0 && errorabsf1[WHICHERROR]>=trueimptryconvalt || PRODUCTION>0 && NOTBADFAILURE(failreturn)==0 && havebackup==0){
8091  // if(NOTBADFAILURE(failreturn)==0){
8092  struct of_state qcheck; get_state(pp, ptrgeom, &qcheck); primtoU(UNOTHING,pp,&qcheck,ptrgeom, uu, NULL);
8093  failnum++; mathematica_report_check(*radinvmod, mathfailtype, failnum, gotfirstnofail, eomtypelocal, itermode, *baseitermethod, errorabsf1, errorabsbestexternal, iter, totaliters, realdt, ptrgeom, ppfirst,pp,pb,piin,prtestUiin,prtestUU0,uu0,uu,Uiin,Ufin, CUf, CUimp, q, dUother);
8094 #if(DEBUGMAXITER)
8095  int usedebugiter=debugiteratteempts[0];
8096  showdebuglist(usedebugiter,pppreholdlist,ppposholdlist,f1reportlist,f1list,errorabsf1list,errorallabsf1list,realiterlist,jaclist,fracdamplist,implicititerlist, implicitferrlist);
8097 #endif
8098 
8099  // report how much MHD inversion used when failed
8100  dualfprintf(fail_file,"nummhdinvsreturn=%d nummhdstepsreturn=%d nstroke=%d\n",*nummhdinvsreturn,*nummhdstepsreturn,nstroke);
8101  }
8102 
8103 
8104 
8105 
8106 
8108  return(failreturn);
8109 
8110 }
8111 
8112 
8113 
8114 
8115 
8116 
8117 
8118 
8119 
8120 
8121 
8122 
8125 #define DEBUGMAXMODE 1
8126 
8128 static void showdebuglist(int debugiter, FTYPE (*pppreholdlist)[NPR],FTYPE (*ppposholdlist)[NPR],FTYPE (*f1reportlist)[NPR],FTYPE (*f1list)[NPR],FTYPE *errorabsf1list,FTYPE *errorallabsf1list, int *realiterlist, FTYPE (*jaclist)[JACNPR][JACNPR], FTYPE *fracdamplist, int *implicititerlist, int *implicitferrlist)
8129 {
8130 
8131  if(DEBUGMAXITER==0) return;
8132 
8133  int listiter;
8134  if(DEBUGMAXMODE==0) dualfprintf(fail_file,"%3s : %3s : %21s %21s %21s %21s %21s %21s %21s %21s %21s : %21s %21s %21s %21s %21s %21s %21s %21s %21s : %21s %21s %21s %21s : %21s %21s : %21s\n","li","ri","rho","ug","v1","v2","v3","Erf","vr1","vr2","vr3","rho","ug","v1","v2","v3","Erf","vr1","vr2","vr3","f1rep0","f1rep1","f1rep2","f1rep3","errorabs","errorallabs","umin");
8135  else if(DEBUGMAXMODE==1) dualfprintf(fail_file,"%3s : %3s : %21s %21s %21s %21s %21s %21s %21s %21s %21s : %21s %21s : %21s %21s %21s %21s %21s %21s %21s %21s %21s %21s %21s %21s : %21s %21s %21s %21s %21s %21s %21s %21s %21s %21s %21s %21s : %21s %21s : %21s : %21s %21s %21s %21s : %21s %21s %21s : %2d %2d\n","li","ri","rho","ug","v1","v2","v3","Erf","vr1","vr2","vr3","rho","ug","f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","frep0","frep1","frep2","frep3","frep4","frep5","frep6","frep7","frep8","frep9","frep10","frep11","errorabs","errorallabs","umin","jac00","jac11","jac22","jac33","fracdtuu0","fracdtG","DAMPFACTOR","it","fe");
8136 
8137  for(listiter=0;listiter<=debugiter;listiter++){
8138  FTYPE umin=calc_PEQ_ufromTrho(TEMPMIN,pppreholdlist[listiter][RHO]);
8139  if(DEBUGMAXMODE==0){
8140  // full, but excessive
8141  dualfprintf(fail_file
8142  ,"%3d : %3d : %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g : %21.15g\n"
8143  ,listiter,realiterlist[listiter]
8144  ,pppreholdlist[listiter][RHO],pppreholdlist[listiter][UU],pppreholdlist[listiter][U1],pppreholdlist[listiter][U2],pppreholdlist[listiter][U3],pppreholdlist[listiter][PRAD0],pppreholdlist[listiter][PRAD1],pppreholdlist[listiter][PRAD2],pppreholdlist[listiter][PRAD3]
8145  ,ppposholdlist[listiter][RHO],ppposholdlist[listiter][UU],ppposholdlist[listiter][U1],ppposholdlist[listiter][U2],ppposholdlist[listiter][U3],ppposholdlist[listiter][PRAD0],ppposholdlist[listiter][PRAD1],ppposholdlist[listiter][PRAD2],ppposholdlist[listiter][PRAD3]
8146  ,f1reportlist[listiter][0],f1reportlist[listiter][1],f1reportlist[listiter][2],f1reportlist[listiter][3]
8147  ,errorabsf1list[listiter]
8148  ,errorallabsf1list[listiter]
8149  ,umin
8150  );
8151  }
8152  else if(DEBUGMAXMODE==1){
8153  // optimal
8154  dualfprintf(fail_file
8155  ,"%3d : %3d : %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g : %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g : %21.15g : %21.15g %21.15g %21.15g %21.15g : %21.15g %21.15g %21.15g : %d %d\n"
8156  ,listiter,realiterlist[listiter]
8157  ,pppreholdlist[listiter][RHO],pppreholdlist[listiter][UU],pppreholdlist[listiter][U1],pppreholdlist[listiter][U2],pppreholdlist[listiter][U3],pppreholdlist[listiter][PRAD0],pppreholdlist[listiter][PRAD1],pppreholdlist[listiter][PRAD2],pppreholdlist[listiter][PRAD3]
8158  ,ppposholdlist[listiter][RHO],ppposholdlist[listiter][UU]
8159  ,f1list[listiter][0],f1list[listiter][1],f1list[listiter][2],f1list[listiter][3],f1list[listiter][4],f1list[listiter][5],f1list[listiter][6],f1list[listiter][7],f1list[listiter][8],f1list[listiter][9],f1list[listiter][10],f1list[listiter][11]
8160  ,f1reportlist[listiter][0],f1reportlist[listiter][1],f1reportlist[listiter][2],f1reportlist[listiter][3],f1reportlist[listiter][4],f1reportlist[listiter][5],f1reportlist[listiter][6],f1reportlist[listiter][7],f1reportlist[listiter][8],f1reportlist[listiter][9],f1reportlist[listiter][10],f1reportlist[listiter][11]
8161  ,errorabsf1list[listiter]
8162  ,errorallabsf1list[listiter]
8163  ,umin
8164  ,jaclist[listiter][0][0]
8165  ,jaclist[listiter][1][1]
8166  ,jaclist[listiter][2][2]
8167  ,jaclist[listiter][3][3]
8168  ,fracdamplist[0] // fracdtuu0
8169  ,fracdamplist[1] // fracdtG
8170  ,fracdamplist[2] // DAMPFACTOR
8171  ,implicititerlist[listiter], implicitferrlist[listiter]
8172  );
8173  }
8174  }// end listiter loop
8175 
8176 }
8177 
8178 
8179 
8180 
8181 
8182 
8183 
8184 int get_rameshsolution_wrapper(int whichcall, int eomtype, FTYPE *errorabs, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, struct of_state *q, FTYPE *ppeng, FTYPE *ppent, FTYPE *uueng, FTYPE *uuent, FTYPE (*dUcompeng)[NPR], FTYPE (*dUcompent)[NPR], struct of_state *qeng, struct of_state *qent, int *failtypeeng, FTYPE *errorabseng, int *iterseng, int *radinvmodeng, int *failtypeent, FTYPE *errorabsent, int *itersent, int *radinvmodent)
8185 {
8186  // BEGIN get ramesh solution
8187  int radinvmod=0; // fake
8188  int failreturnentropy=0; // fake
8189  // int failtypeeng=1,failtypeent=1,iterseng=IMPMAXITERLONG,itersent=IMPMAXITERLONG;
8190  int failnum=0,gotfirstnofail=0;
8191  int itermode=ITERMODENORMAL,iters=IMPMAXITERLONG;
8192  int baseitermethod=QTYPMHD;
8193  FTYPE errorabsbestexternal[2];
8194  set_array(errorabsbestexternal,2,MPI_FTYPE,BIG);
8195  // itersentropy is last, but might feed in best
8196  int isexplicit=0;
8197  FTYPE realdt = compute_dt(isexplicit,CUf, CUimp,dt);
8198  // get uu0
8199  FTYPE uu0[NPR];
8200  FTYPE fracdtuu0=1.0;
8201  int pliter,pl;
8202  FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
8203  PLOOP(pliter,pl) uu0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall);
8204  FTYPE uu[NPR]; // not used except when doing diagnostics in ramesh code
8205  // FTYPE uueng[NPR],uuent[NPR]; // filled with answer if successful
8206  //
8207  get_rameshsolution(whichcall, radinvmod, failreturnentropy, failnum, gotfirstnofail, eomtype, itermode, baseitermethod, errorabs, errorabs, iters, iters, realdt, ptrgeom, pp, pp, piin, uu0, uu, Uiin, Ufin, CUf, CUimp, q, ppeng, ppent, uueng, uuent, qeng, qent, failtypeeng, errorabseng, iterseng, radinvmodeng, failtypeent, errorabsent, itersent, radinvmodent);
8208  //
8209  // pp and q are assigned, but external call might just use only *eng and *ent versions of these and other things.
8210  if(eomtype==EOMGRMHD){
8211  PLOOP(pliter,pl) pp[pl]=ppeng[pl];
8212  *q=*qeng;
8213  }
8214  if(eomtype==EOMENTROPYGRMHD){
8215  PLOOP(pliter,pl) pp[pl]=ppent[pl];
8216  *q=*qent;
8217  }
8218  //
8219  int sc;
8220  sc = RADSOURCE;
8221  PLOOP(pliter,pl){
8222  dUcompeng[sc][pl] = + (uueng[pl]-uu0[pl])/realdt;
8223  dUcompent[sc][pl] = + (uuent[pl]-uu0[pl])/realdt;
8224  }
8225  // END WITH RAMESH SOLUTION
8226 
8227 #if(0)
8228  // DEBUG
8229  sc = RADSOURCE;
8230  PLOOP(pliter,pl){
8231  if(1||!isfinite(dUcompeng[sc][pl])) dualfprintf(fail_file,"POOPENG %g %g %g\n",uueng[pl],uu0[pl],realdt);
8232  if(1||!isfinite(dUcompent[sc][pl])) dualfprintf(fail_file,"POOPENT %g %g %g\n",uuent[pl],uu0[pl],realdt);
8233  }
8234 #endif
8235 
8236 
8237  return(0);
8238 }
8239 
8240 //#define WHICHVELRAMESH VEL4 // should be same as WHICHVEL in test.f
8241 #define WHICHVELRAMESH VELREL4 // should be same as WHICHVEL in test.f
8242 
8243 int get_rameshsolution(int whichcallramesh, int radinvmod, int failtype, long long int failnum, int gotfirstnofail, int eomtypelocal, int itermode, int baseitermethod, FTYPE *errorabs, FTYPE *errorabsbestexternal, int iters, int totaliters, FTYPE realdt, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *pb, FTYPE *piin, FTYPE *uu0, FTYPE *uu, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_state *q, FTYPE *ppeng, FTYPE *ppent, FTYPE *uueng, FTYPE *uuent, struct of_state *qeng, struct of_state *qent, int *failtypeeng, FTYPE *errorabseng, int *iterseng, int *radinvmodeng, int *failtypeent, FTYPE *errorabsent, int *itersent, int *radinvmodent)
8244 {
8245  // int failtype=1;
8246  // long long int failnum=0;
8247  // int gotfirstnofail=0;
8248  // int eomtypelocal=EOMGRMHD;
8249  // int itermode=ITERMODENORMAL;
8250  // FTYPE errorabs=BIG;
8251  // FTYPE iters=IMPMAXITERLONG;
8252  // FTYPE errorabsbestexternal=BIG;
8253  // int totaliters=IMPMAXITERLONG;
8254  FTYPE *ppfirst=pp,*prtestUiin=piin,*prtestUU0=piin;
8255  struct of_state *qpp=q;
8256  struct of_state *qpb=q;
8257  struct of_state *qpiin=q;
8258  int jj,kk;
8259  int pliter,pl;
8260 
8261 
8262 
8263  // 11 vars, failcode, error, iterations
8264  // MUST BE SAME AS IN test.f code
8265 #define NUMRESULTS 15
8266  doublereal resultseng[NUMRESULTS]={0},resultsent[NUMRESULTS]={0};
8267 
8268 
8269  if(WHICHVELRAMESH==VEL4 && ptrgeom->gcov[GIND(TT,TT)]>=0.0 || WHICHEOS!=IDEALGAS){
8270  // KORALTODO SUPERGODMARK: Also only can use ramesh if lambda cooling only includes kappaff inverse and only normal ff and es opacities.
8271  if(WHICHVELRAMESH==VEL4 && ptrgeom->gcov[GIND(TT,TT)]>=0.0) dualfprintf(fail_file,"Wanted to call ramesh, but inside ergosphere\n");
8272  *failtypeeng = 1;
8273  *radinvmodent = 0;
8274  errorabseng[0] = errorabseng[1] = BIG;
8275  *iterseng = 0;
8276  *failtypeent = 1;
8277  *radinvmodent = 0;
8278  errorabsent[0] = errorabsent[1] = BIG;
8279  *itersent = 0;
8280  for(pl=0;pl<NUMRESULTS;pl++) resultseng[pl]=resultsent[pl]=-1.0;
8281  PLOOP(pliter,pl) ppeng[pl]=ppent[pl]=-1.0;
8282  }
8283  else{
8284 
8286  //
8287  // Call Ramesh's solver
8288  //
8290 
8291 
8292  // below things must be same order as in test.f
8293  // MUST BE SAME AS IN test.f code
8294 #define NUMARGS (211+11)
8295 
8296  // call fortran code
8297  doublereal args[NUMARGS]={0};
8298  int na;
8299 
8300  na=-1;
8301  na++; args[na]=(doublereal)NUMARGS;
8302  na++; args[na]=(doublereal)NUMRESULTS;
8303  na++; args[na]=(doublereal)WHICHVELRAMESH;
8304  na++; args[na]=(doublereal)failtype;
8305  na++; args[na]=(doublereal)myid;
8306  na++; args[na]=(doublereal)failnum;
8307  na++; args[na]=(doublereal)gotfirstnofail;
8308  na++; args[na]=(doublereal)eomtypelocal;
8309  na++; args[na]=(doublereal)itermode;
8310  na++; args[na]=errorabs[WHICHERROR];
8311  na++; args[na]=errorabsbestexternal[WHICHERROR];
8312  na++; args[na]=(doublereal)iters;
8313  na++; args[na]=(doublereal)totaliters;
8314  na++; args[na]=realdt;
8315  na++; args[na]=(doublereal)nstep;
8316  na++; args[na]=(doublereal)steppart;
8317  na++; args[na]=gam;
8318  na++; args[na]=GAMMAMAXRAD;
8319  na++; args[na]=ERADLIMIT;
8320  FTYPE trueimptryconv=IMPTRYCONV;
8321  na++; args[na]=IMPTRYCONVABS;
8322  na++; args[na]=IMPALLOWCONVCONSTABS;
8323  na++; args[na]=ARAD_CODE;
8324  // so as really code uses:
8325  na++; args[na]=calc_kappaes_user(1.0,1.0,0,0,0);
8326  na++; args[na]=calc_kappa_user(1.0,1.0,1.0,1.0,1.0,0,0,0);
8327  na++; args[na]=0.0;
8328  DLOOP(jj,kk){ na++; args[na]=ptrgeom->gcon[GIND(jj,kk)];}
8329  DLOOP(jj,kk){ na++; args[na]=ptrgeom->gcov[GIND(jj,kk)];}
8330  PLOOP(pliter,pl){ na++; args[na]=pp[pl]; na++; args[na]=ppfirst[pl]; na++; args[na]=pb[pl]; na++; args[na]=piin[pl]; na++; args[na]=prtestUiin[pl]; na++; args[na]=prtestUU0[pl]; na++; args[na]=uu0[pl]; na++; args[na]=uu[pl]; na++; args[na]=Uiin[pl]; }
8331  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj){ na++; args[na]=qpp->uradcon[jj]; na++; args[na]=qpp->uradcov[jj]; }
8332  else DLOOPA(jj){ na++; args[na]=0.0; na++; args[na]=0.0; }
8333  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj){ na++; args[na]=qpp->ucon[jj]; na++; args[na]=qpp->ucov[jj]; }
8334  else DLOOPA(jj){ na++; args[na]=0.0; na++; args[na]=0.0; }
8335 
8336  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj){ na++; args[na]=qpb->uradcon[jj]; na++; args[na]=qpb->uradcov[jj]; }
8337  else DLOOPA(jj){ na++; args[na]=0.0; na++; args[na]=0.0; }
8338  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj){ na++; args[na]=qpb->ucon[jj]; na++; args[na]=qpb->ucov[jj]; }
8339  else DLOOPA(jj){ na++; args[na]=0.0; na++; args[na]=0.0; }
8340 
8341  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj){ na++; args[na]=qpiin->uradcon[jj]; na++; args[na]=qpiin->uradcov[jj]; }
8342  else DLOOPA(jj){ na++; args[na]=0.0; na++; args[na]=0.0; }
8343  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj){ na++; args[na]=qpiin->ucon[jj]; na++; args[na]=qpiin->ucov[jj]; }
8344  else DLOOPA(jj){ na++; args[na]=0.0; na++; args[na]=0.0; }
8345 
8346  if(na!=NUMARGS-1){
8347  dualfprintf(fail_file,"Wrong number of args=%d\n",na);
8348  myexit(304583453);
8349  }
8350 
8351  // calling f2c generated code, which assumes single array as input of 211 items.
8352  rameshsolver_(args,resultseng,resultsent);
8353 
8354  // process results from rameshsolver()
8355 
8356  *failtypeeng = (int)resultseng[11];
8357  if(*failtypeeng==0){
8358  PLOOPBONLY(pl) ppeng[pl]=pp[pl]; // ramesh solver doesn't pass this back
8359  FTYPE uconeng[NDIM],uradconeng[NDIM];
8360  // return solution in harm format
8361  ppeng[RHO] = resultseng[0];
8362  ppeng[UU] = ppeng[ENTROPY] = resultseng[1];
8363  if(WHICHVELRAMESH==VEL4){
8364  uconeng[0] = resultseng[2];
8365  uconeng[1] = resultseng[3];
8366  uconeng[2] = resultseng[4];
8367  uconeng[3] = resultseng[5];
8368  uconrel(uconeng,&ppeng[UU],ptrgeom); // get \tilde{u}^i
8369  }
8370  else{
8371  SLOOPA(jj) ppeng[UU+jj] = resultseng[2+jj];
8372  }
8373  ppeng[URAD0] = resultseng[6];
8374  if(WHICHVELRAMESH==VEL4){
8375  uradconeng[0] = resultseng[7];
8376  uradconeng[1] = resultseng[8];
8377  uradconeng[2] = resultseng[9];
8378  uradconeng[3] = resultseng[10];
8379  uconrel(uradconeng,&ppeng[URAD0],ptrgeom); // get \tilde{u}^i_{\rm rad}
8380  }
8381  else{
8382  SLOOPA(jj) ppeng[URAD0+jj] = resultseng[7+jj];
8383  }
8384  // get full state (thermo and other stuff needed)
8385  get_state(ppeng,ptrgeom,qeng);
8386  primtoU(UNOTHING,ppeng, qeng, ptrgeom, uueng, NULL);
8387  extern int invert_scalars1(struct of_geom *ptrgeom, FTYPE *Ugeomfree, FTYPE *pr);
8388  invert_scalars1(ptrgeom, uueng,ppeng);
8389  extern int invert_scalars2(struct of_geom *ptrgeom, FTYPE *Ugeomfree, struct of_state *q, FTYPE *pr);
8390  invert_scalars2(ptrgeom, uueng,qeng,ppeng);
8391  }
8392  errorabseng[0] = resultseng[12];
8393  *iterseng = (int)resultseng[13];
8394  *radinvmodeng = (int)resultseng[14];
8395 
8396  // override ramesh error in case meaningless, if there is a failure.
8397  if(*failtypeeng) errorabseng[0] = BIG;
8398 
8399  // return solution in harm format
8400  *failtypeent = (int)resultsent[11];
8401  if(*failtypeent==0){
8402  PLOOPBONLY(pl) ppent[pl]=pp[pl]; // ramesh solver doesn't pass this back
8403  FTYPE uconent[NDIM],uradconent[NDIM];
8404  ppent[RHO] = resultsent[0];
8405  ppent[UU] = ppent[ENTROPY] = resultsent[1];
8406  if(WHICHVELRAMESH==VEL4){
8407  uconent[0] = resultsent[2];
8408  uconent[1] = resultsent[3];
8409  uconent[2] = resultsent[4];
8410  uconent[3] = resultsent[5];
8411  uconrel(uconent,&ppent[UU],ptrgeom); // get \tilde{u}^i
8412  }
8413  else{
8414  SLOOPA(jj) ppent[UU+jj] = resultsent[2+jj];
8415  }
8416  ppent[URAD0] = resultsent[6];
8417  if(WHICHVELRAMESH==VEL4){
8418  uradconent[0] = resultsent[7];
8419  uradconent[1] = resultsent[8];
8420  uradconent[2] = resultsent[9];
8421  uradconent[3] = resultsent[10];
8422  uconrel(uradconent,&ppent[URAD0],ptrgeom); // get \tilde{u}^i_{\rm rad}
8423  }
8424  else{
8425  SLOOPA(jj) ppent[URAD0+jj] = resultsent[7+jj];
8426  }
8427  // get full state (thermo and other stuff needed)
8428  get_state(ppent,ptrgeom,qent);
8429  primtoU(UNOTHING,ppent, qent, ptrgeom, uuent, NULL);
8430  extern int invert_scalars1(struct of_geom *ptrgeom, FTYPE *Ugeomfree, FTYPE *pr);
8431  invert_scalars1(ptrgeom, uuent,ppent);
8432  extern int invert_scalars2(struct of_geom *ptrgeom, FTYPE *Ugeomfree, struct of_state *q, FTYPE *pr);
8433  invert_scalars2(ptrgeom, uuent,qent,ppent);
8434  }
8435  errorabsent[0] = resultsent[12];
8436  *itersent = (int)resultsent[13];
8437  *radinvmodent = (int)resultsent[14];
8438 
8439  // override ramesh error in case meaningless, if there is a failure.
8440  if(*failtypeent) errorabsent[0] = BIG;
8441  }
8442 
8443 
8444 
8446  //
8447  // Double check ramesh error with f_error_check() or f_implicit(). Also uses error as consistent with harm -- i.e. total error if WHICHERROR==1
8448  //
8450  int failreturnferr;
8451  int allowbaseitermethodswitch=0;
8452  int fakeiter=1;
8453  int fakef1iter=-1;
8454  int failreturnallowableuse=0;
8455  int whichcall=FIMPLICITCALLTYPEFINALCHECK2;
8456  FTYPE impepsjac=0;
8457  int showmessages=0;
8458  int showmessagesheavy=0;
8459  int allowlocalfailurefixandnoreport=0;
8460  //int &eomtypelocal;
8461  int whichcap=CAPTYPEBASIC;
8462  // int itermode;
8463  // int baseitermethod;
8464  FTYPE fracenergy=1.0;
8465  FTYPE dissmeasure=-1.0;
8466  radinvmod=*radinvmodeng; // default
8467  FTYPE trueimptryconv=IMPTRYCONV;
8468  FTYPE trueimptryconvabs=IMPTRYCONVABS;
8469  FTYPE trueimpallowconvabs=IMPALLOWCONVCONSTABS;
8470  int trueimpmaxiter=IMPMAXITERLONG;
8471  // FTYPE realdt;
8472  int dimtypef=DIMTYPEFCONS;
8473  // some geometry stuff to store pre-step instead of for each step.
8474  int jjdim;
8475  FTYPE dimfactU[NPR];
8476  PLOOP(pliter,pl) dimfactU[pl]=1.0; // default
8477  DLOOPA(jjdim) dimfactU[UU+jjdim]=dimfactU[URAD0+jjdim]=sqrt(fabs(ptrgeom->gcon[GIND(jjdim,jjdim)]));
8478  SLOOPA(jjdim) dimfactU[B1+jjdim-1] = 1.0/dimfactU[U1+jjdim-1];
8479  FTYPE ppppp[NPR];
8480  // FTYPE pp[NPR];
8481  // FTYPE piin[NPR];
8482  FTYPE uuppp[NPR];
8483  //FTYPE Uiin[NPR];
8484  // FTYPE uu0[NPR];
8485  // FTYPE uu[NPR];
8486  FTYPE fracdtG=1.0;
8487  //FTYPE ptrgeom;
8488  //FTYPE q;
8489  FTYPE f1[NPR];
8490  FTYPE f1norm[NPR];
8491  FTYPE f1report[NPR];
8492  int goexplicit=0;
8493  FTYPE errorabsf1[NUMERRORTYPES];
8494  // WHICHERROR;
8495  int convreturnf1;
8496  FTYPE tautotmaxreturn;
8497 
8498 
8499  int nummhdinvsreturn=0;
8500  struct of_method mtd;
8501  struct of_refU ru;
8502  if(*failtypeeng==0){
8504  //
8505  // test ppeng
8506  //
8508  PLOOP(pliter,pl){
8509  ppppp[pl] = pp[pl] = ppeng[pl];
8510  uuppp[pl] = uu[pl] = uueng[pl];
8511  }
8512 
8513 
8514  failreturnferr=f_implicit(allowbaseitermethodswitch, fakeiter, fakef1iter, failreturnallowableuse, whichcall, impepsjac, showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, &baseitermethod, fracenergy, dissmeasure, &radinvmod, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, ppppp, pp, piin, uuppp, Uiin, uu0, uu, fracdtG*realdt, ptrgeom, q, f1, f1norm, f1report, &goexplicit, &errorabsf1[0], &errorabsf1[1], WHICHERROR, &convreturnf1, &nummhdinvsreturn, &tautotmaxreturn, &mtd, &ru); // modifies uu and pp, f1poret, goexplicit, errorabsf1[0,1], convreturnf1
8515  // translate result
8516  // *qeng=*q; // already done
8517  *failtypeeng=failreturnferr; // trust my error report
8518  errorabseng[0]=errorabsf1[0]; // trust my error measure
8519  errorabseng[1]=errorabsf1[1]; // trust my error measure
8520  *radinvmodeng=radinvmod; // trust my rad inv check
8521  }
8522 
8523  if(*failtypeent==0){
8525  //
8526  // test ppent
8527  //
8529  PLOOP(pliter,pl){
8530  ppppp[pl] = pp[pl] = ppent[pl];
8531  uuppp[pl] = uu[pl] = uuent[pl];
8532  }
8533 
8534  failreturnferr=f_implicit(allowbaseitermethodswitch, fakeiter, fakef1iter, failreturnallowableuse, whichcall, impepsjac, showmessages, showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocal, whichcap, itermode, &baseitermethod, fracenergy, dissmeasure, &radinvmod, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, ppppp, pp, piin, uuppp, Uiin, uu0, uu, fracdtG*realdt, ptrgeom, q, f1, f1norm, f1report, &goexplicit, &errorabsf1[0], &errorabsf1[1], WHICHERROR, &convreturnf1, &nummhdinvsreturn, &tautotmaxreturn, &mtd, &ru); // modifies uu and pp, f1poret, goexplicit, errorabsf1[0,1], convreturnf1
8535  // translate result
8536  // *qent=*q; // already done
8537  *failtypeent=failreturnferr; // trust my error report
8538  errorabsent[0]=errorabsf1[0]; // trust my error measure
8539  errorabsent[1]=errorabsf1[1]; // trust my error measure
8540  *radinvmodent=radinvmod; // trust my rad inv check
8541  }
8542 
8543 
8544 
8545 
8546  // DEBUG and only when real call (for now) and only show if one is not a bad solution
8547  if(debugfail>=2 && whichcallramesh>0 && (*failtypeent==0 || *failtypeeng==0)){ // NORMAL
8548  // if(debugfail>=2 && whichcallramesh==0){ // DEBUGGING Erf~0 solutions
8549  // if(PRODUCTION==0 && debugfail>=2 && (*failtypeeng==0 || *failtypeent==0)){ // DEBUGGING Erf~0 solutions
8550 
8551  FTYPE resultsjon[NUMRESULTS];
8552  resultsjon[0] = pp[RHO];
8553  resultsjon[1] = pp[UU];
8554  if(WHICHVELRAMESH==VEL4){
8555  resultsjon[2] = q->ucon[0];
8556  resultsjon[3] = q->ucon[1];
8557  resultsjon[4] = q->ucon[2];
8558  resultsjon[5] = q->ucon[3];
8559  }
8560  else{
8561  resultsjon[2] = 0.0;
8562  SLOOPA(jj) resultsjon[2+jj] = pp[UU+jj];
8563  }
8564  resultsjon[6] = pp[URAD0];
8565  if(WHICHVELRAMESH==VEL4){
8566  resultsjon[7] = q->uradcon[0];
8567  resultsjon[8] = q->uradcon[1];
8568  resultsjon[9] = q->uradcon[2];
8569  resultsjon[10] = q->uradcon[3];
8570  }
8571  else{
8572  resultsjon[7]=0.0;
8573  SLOOPA(jj) resultsjon[7+jj] = pp[URAD0+jj];
8574  }
8575  resultsjon[11] = (FTYPE)failtype;
8576  resultsjon[12] = errorabs[WHICHERROR];
8577  resultsjon[13] = (FTYPE)iters;
8578  resultsjon[14] = radinvmod;
8579 
8580  for(pl=0;pl<NUMRESULTS;pl++) dualfprintf(fail_file,"RAMESH1: pl=%d | resultsjon=%21.15g | resultseng=%21.15g resultsent=%21.15g\n",pl,resultsjon[pl],resultseng[pl],resultsent[pl]);
8581  SLOOPA(jj) dualfprintf(fail_file,"RAMESH2: jj=%d utildegasjon=%21.15g utildegaseng=%21.15g utildegasent=%21.15g\n",jj,pp[U1+jj-1],ppeng[U1+jj-1],ppent[U1+jj-1]);
8582  SLOOPA(jj) dualfprintf(fail_file,"RAMESH3: jj=%d utilderadjon=%21.15g utilderadeng=%21.15g utilderadent=%21.15g\n",jj,pp[URAD1+jj-1],ppeng[URAD1+jj-1],ppent[URAD1+jj-1]);
8583  PLOOP(pliter,pl) dualfprintf(fail_file,"RAMESH3.5: pl=%d ppeng=%21.15g uueng=%21.15g ppent=%21.15g uuent=%21.15g\n",pl,ppeng[pl],uueng[pl],ppent[pl],ppeng[pl]);
8584 
8585  // get radiative inversion stuff for Ramesh
8586  FTYPE Er,Utildesq,Utildecon[NDIM];
8587 
8588  compute_ZAMORAD(uu0, ptrgeom, &Er, &Utildesq, Utildecon);
8589  dualfprintf(fail_file,"RAMESH4: E_r=%21.15g Utildesq=%21.15g Utildecon0=%21.15g Utildecon1=%21.15g Utildecon2=%21.15g Utildecon3=%21.15g\n",Er,Utildesq,Utildecon[0],Utildecon[1],Utildecon[2],Utildecon[3]);
8590 
8591  if(*failtypeeng==0){
8592  compute_ZAMORAD(uueng, ptrgeom, &Er, &Utildesq, Utildecon);
8593  dualfprintf(fail_file,"RAMESH5: E_r=%21.15g Utildesq=%21.15g Utildecon0=%21.15g Utildecon1=%21.15g Utildecon2=%21.15g Utildecon3=%21.15g\n",Er,Utildesq,Utildecon[0],Utildecon[1],Utildecon[2],Utildecon[3]);
8594  }
8595 
8596  if(*failtypeent==0){
8597  compute_ZAMORAD(uuent, ptrgeom, &Er, &Utildesq, Utildecon);
8598  dualfprintf(fail_file,"RAMESH6: E_r=%21.15g Utildesq=%21.15g Utildecon0=%21.15g Utildecon1=%21.15g Utildecon2=%21.15g Utildecon3=%21.15g\n",Er,Utildesq,Utildecon[0],Utildecon[1],Utildecon[2],Utildecon[3]);
8599  }
8600 
8601  }// end if DEBUG
8602 
8603  return(0);
8604 }
8605 
8606 
8607 
8608 int mathematica_report_check(int radinvmod, int failtype, long long int failnum, int gotfirstnofail, int eomtypelocal, int itermode, int baseitermethod, FTYPE *errorabs, FTYPE *errorabsbestexternal, int iters, int totaliters, 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, FTYPE *CUimp, struct of_state *q, FTYPE *dUother)
8609 {
8610  int jj,kk;
8611  int pliter,pl;
8612 
8613 
8614  if(0){ // old mathematica style
8615  dualfprintf(fail_file,"FAILINFO: %d %d %lld %d\ndt=%21.15g\n",failtype, myid, failnum, gotfirstnofail,realdt);
8616  DLOOP(jj,kk) dualfprintf(fail_file,"gn%d%d=%21.15g\n",jj+1,kk+1,ptrgeom->gcon[GIND(jj,kk)]);
8617  DLOOP(jj,kk) dualfprintf(fail_file,"gv%d%d=%21.15g\n",jj+1,kk+1,ptrgeom->gcov[GIND(jj,kk)]);
8618  // shows first pp(uu0)
8619  PLOOP(pliter,pl) dualfprintf(fail_file,"pp%d=%21.15g\npb%d=%21.15g\nuu0%d=%21.15g\nuu%d=%21.15g\nuui%d=%21.15g\n",pl,pp[pl],pl,pb[pl],pl,uu0[pl],pl,uu[pl],pl,Uiin[pl]);
8620  struct of_state qreport;
8621  get_state(pp,ptrgeom,&qreport);
8622  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj) dualfprintf(fail_file,"uradcon%d=%21.15g\nuradcov%d=%21.15g\n",jj,qreport.uradcon[jj],jj,qreport.uradcov[jj]);
8623  else DLOOPA(jj) dualfprintf(fail_file,"uradcon%d=%21.15g\nuradcov%d=%21.15g\n",jj,0.0,jj,0.0);
8624  DLOOPA(jj) dualfprintf(fail_file,"ucon%d=%21.15g\nucov%d=%21.15g\n",jj,qreport.ucon[jj],jj,qreport.ucov[jj]);
8625  // then do:
8626  // 1) grep -A 134 --text FAILINFO 0_fail.out.grmhd* > fails.txt
8627  // 2) emacs regexp: \([0-9]\)e\([-+]*[0-9]+\) -> \1*10^(\2)
8628  }
8629  else{
8630 
8632  //
8633  // Fix-up some terms to avoid nan or inf in output.
8634  //
8636 
8637  if(!isfinite(pp[UU])) pp[UU]=BIG;
8638  if(!isfinite(pp[ENTROPY])) pp[ENTROPY]=BIG;
8639  if(!isfinite(errorabs[0])) errorabs[0]=BIG;
8640  if(!isfinite(errorabs[1])) errorabs[1]=BIG;
8641  if(!isfinite(errorabsbestexternal[0])) errorabsbestexternal[0]=BIG;
8642  if(!isfinite(errorabsbestexternal[1])) errorabsbestexternal[1]=BIG;
8643 
8645  //
8646  // Get state for pp,pb,piin
8647  //
8649 
8650 
8651  struct of_state qpp;
8652  get_state(pp,ptrgeom,&qpp);
8653  struct of_state qpb;
8654  get_state(pb,ptrgeom,&qpb);
8655  struct of_state qpiin;
8656  get_state(piin,ptrgeom,&qpiin);
8657 
8659  //
8660  // Output stuff for mathematica
8661  //
8663 
8664  // 211+11 things
8665  dualfprintf(fail_file,"\nFAILINFO: ");
8666  dualfprintf(fail_file,"%d %d %d ",NUMARGS,NUMRESULTS,WHICHVELRAMESH); // 3
8667  dualfprintf(fail_file,"%d %d %lld %d %d %d %21.15g %21.15g %d %d %21.15g %lld %d %21.15g ",failtype,myid,failnum,gotfirstnofail,eomtypelocal,itermode,errorabs[WHICHERROR],errorabsbestexternal[WHICHERROR],iters,totaliters,realdt,nstep,steppart,gam); // 14
8668  FTYPE trueimptryconv=IMPTRYCONV;
8669  dualfprintf(fail_file,"%21.15g %21.15g %21.15g %21.15g ",GAMMAMAXRAD,ERADLIMIT,IMPTRYCONVABS,IMPALLOWCONVCONSTABS); // 4
8670  dualfprintf(fail_file,"%21.15g %21.15g %21.15g %21.15g ",ARAD_CODE,calc_kappaes_user(1.0,1.0,0,0,0),calc_kappa_user(1.0,1.0,1.0,1.0,1.0,0,0,0),0.0); // 4
8671  DLOOP(jj,kk) dualfprintf(fail_file,"%21.15g ",ptrgeom->gcon[GIND(jj,kk)]); // 16
8672  DLOOP(jj,kk) dualfprintf(fail_file,"%21.15g ",ptrgeom->gcov[GIND(jj,kk)]); // 16
8673  PLOOP(pliter,pl) dualfprintf(fail_file,"%21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g %21.15g ",pp[pl],ppfirst[pl],pb[pl],piin[pl],prtestUiin[pl],prtestUU0[pl],uu0[pl],uu[pl],Uiin[pl]); // 9*13
8674  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",qpp.uradcon[jj],qpp.uradcov[jj]); // 4*2=8
8675  else DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",0.0,0.0);
8676  DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",qpp.ucon[jj],qpp.ucov[jj]); // 4*2=8
8677  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",qpb.uradcon[jj],qpb.uradcov[jj]); // 4*2=8
8678  else dualfprintf(fail_file,"%21.15g %21.15g ",0.0,0.0);
8679  DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",qpb.ucon[jj],qpb.ucov[jj]); // 4*2=8
8680  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",qpiin.uradcon[jj],qpiin.uradcov[jj]); // 4*2=8
8681  else dualfprintf(fail_file,"%21.15g %21.15g ",0.0,0.0);
8682  DLOOPA(jj) dualfprintf(fail_file,"%21.15g %21.15g ",qpiin.ucon[jj],qpiin.ucov[jj]); // 4*2=8
8683  dualfprintf(fail_file,"\n");
8684 
8685 
8686 
8687  // get ramesh solution
8688  int whichcall=0; // debug call
8689  FTYPE ppeng[NPR]={0},ppent[NPR]={0},errorabseng[NUMERRORTYPES],errorabsent[NUMERRORTYPES];
8690  set_array(errorabseng,NUMERRORTYPES,MPI_FTYPE,BIG);
8691  set_array(errorabsent,NUMERRORTYPES,MPI_FTYPE,BIG);
8692 
8693  FTYPE uueng[NPR]={0},uuent[NPR]={0};
8694  int failtypeeng=1,failtypeent=1,iterseng=IMPMAXITERLONG,itersent=IMPMAXITERLONG, radinvmodeng=UTOPRIMRADFAILBAD1, radinvmodent=UTOPRIMRADFAILBAD1;
8695  struct of_state qeng=*q,qent=*q;
8696 
8697  // No longer is rameshsolution() up to date with # of args or opacity physics
8698  // get_rameshsolution(whichcall, radinvmod, failtype, failnum, gotfirstnofail, eomtypelocal, itermode, baseitermethod, errorabs, errorabsbestexternal, iters, totaliters,realdt, ptrgeom, pp, pb, piin, uu0, uu, Uiin, Ufin, CUf, CUimp, q, ppeng, ppent, uueng, uuent, &qeng, &qent, &failtypeeng, errorabseng, &iterseng, &radinvmodeng, &failtypeent, errorabsent, &itersent, &radinvmodent);
8699 
8700 
8701 
8703  //
8704  // FAILRETURNABLE
8705  //
8707  dualfprintf(fail_file,"\nFAILREPEATABLE: %d %d %lld : ",failtype,myid,failnum);
8708  dualfprintf(fail_file,"dt=%21.15g;CUf[2]=%21.15g;gam=%21.15g;",realdt,CUf[2],gam);
8709  PLOOP(pliter,pl) dualfprintf(fail_file,"pp[%d]=%21.15g;ppfirst[%d]=%21.15g;pb[%d]=%21.15g;piin[%d]=%21.15g;Uiin[%d]=%21.15g;Ufin[%d]=%21.15g;dUother[%d]=%21.15g;",pl,pp[pl],pl,ppfirst[pl],pl,pb[pl],pl,piin[pl],pl,Uiin[pl],pl,Ufin[pl],pl,dUother[pl]);
8710  // ptrgeom stuff
8711  DLOOP(jj,kk) dualfprintf(fail_file,"ptrgeom->gcov[GIND(%d,%d)]=%21.15g;ptrgeom->gcon[GIND(%d,%d)]=%21.15g;",jj,kk,ptrgeom->gcov[GIND(jj,kk)],jj,kk,ptrgeom->gcon[GIND(jj,kk)]);
8712  DLOOPA(jj) dualfprintf(fail_file,"ptrgeom->gcovpert[%d]=%21.15g;ptrgeom->beta[%d]=%21.15g;",jj,ptrgeom->gcovpert[jj],jj,ptrgeom->beta[jj]);
8713  dualfprintf(fail_file,"ptrgeom->alphalapse=%21.15g;ptrgeom->betasqoalphasq=%21.15g;ptrgeom->gdet=%21.15g;ptrgeom->igdetnosing=%21.15g;ptrgeom->i=%d;ptrgeom->j=%d;ptrgeom->k=%d;ptrgeom->p=%d;",ptrgeom->alphalapse,ptrgeom->betasqoalphasq,ptrgeom->gdet,ptrgeom->igdetnosing,ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p);
8714  if(q!=NULL){
8715  DLOOPA(jj) dualfprintf(fail_file,"q->ucon[%d]=%21.15g;q->ucov[%d]=%21.15g;",jj,q->ucon[jj],jj,q->ucov[jj]);
8716  if(EOMRADTYPE!=EOMRADNONE) DLOOPA(jj) dualfprintf(fail_file,"q->uradcon[%d]=%21.15g;q->uradcov[%d]=%21.15g;",jj,q->uradcon[jj],jj,q->uradcov[jj]);
8717  else DLOOPA(jj) dualfprintf(fail_file,"q->uradcon[%d]=%21.15g;q->uradcov[%d]=%21.15g;",jj,0.0,jj,0.0);
8718  dualfprintf(fail_file,"q->pressure=%21.15g;q->entropy=%21.15g;q->ifremoverestplus1ud0elseud0=%21.15g;",q->pressure,q->entropy,q->ifremoverestplus1ud0elseud0);
8719  }
8720  dualfprintf(fail_file,"\n");
8721 
8722 
8723  // then do:
8724  // 1) grep -h --text FAILINFO 0_fail.out.grmhd* | sed 's/FAILINFO: //g'| sort -T ./ -r -g -k 10 > fails.txt
8725  //
8726  // or:
8727  // grep -h --text FAILINFO 0_fail.out.grmhd* | grep -v "FAILINFO: 100" |grep -v "FAILINFO: 80"| sed 's/FAILINFO: //g' | sort -T ./ -r -g -k 7 > failshigherror.txt ; head -100 failshigherror.txt > failshigherror100.txt
8728  //
8729 
8730  // grep --text BAD 0_fail.out.grmhd.00*|wc -l ; grep FAILINFO 0_fail.out.grmhd.00*|wc -l ; grep MAXF1 0_fail.out.grmhd.00*| wc -l ; grep MAXITER 0_fail.out.grmhd.00*|wc -l ; grep "also failed" 0_fail.out.grmhd.00*|wc -l
8731 
8732  // TO CHECK ON DAMPING:
8733  // grep -i "Damping worked" 0_fail.out.grmhd.00*|wc -l ; grep -i "Damping failed" 0_fail.out.grmhd.00*|wc -l
8734 
8735  // see if any MAXF1ITER: less -S fails.txt| awk '{print $1}'|sort|less
8736 
8737  // 2) Choose numfails in below mathematica script
8738 
8739  // 3) ~/bin/math < /data/jon/harm_math/solveimplicit_superwrapper.m
8740  // or: nohup ~/bin/math < /data/jon/harm_math/solveimplicit_superwrapper.m &> math.out &
8741  // or: preferred: ~/bin/math < /data/jon/harm_math/solveimplicit_superwrapper.m &> math.out &
8742 
8743  // 4) grep 0Good math.out
8744  // if any Good's appear, mathematica found solution when harm did not. Fix it!
8745 
8746  // If any appear in grep 0WGood math.out , then precision issue with long doubles in harm even.
8747 
8748  // If any appear in grep 0MGood math.out , then gammamax case should work!
8749 
8750  // 5) More advanced version of #4. Use check.sh script:
8751  // bash /data/jon/harmgit/scripts/check.sh math.out . Gives overall report.
8752  }
8753 
8754 
8755 
8756  return(0);
8757 }
8758 
8759 
8760 
8763 static int f_error_check(int showmessages, int showmessagesheavy, int iter, FTYPE conv, FTYPE convabs, FTYPE realdt, int dimtypef, int eomtype, int radinvmod, int itermode, int baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, FTYPE *dimfactU, FTYPE *pp, FTYPE *piin, FTYPE *fin, FTYPE *finnorm, FTYPE *finreport, FTYPE *Uiin, FTYPE *uu0, FTYPE *uu, struct of_geom *ptrgeom, FTYPE *errorabs, FTYPE *errorallabs, int whicherror,struct of_method *mtd, struct of_refU *ru)
8764 {
8765  int ii,jj;
8766  int pliter,pl;
8767  int passedconv[2];
8768 
8769  // default
8770  passedconv[0]=passedconv[1]=0;
8771 
8772  // get error
8773  // NOTE: use of gcov[ii,ii] so comparable dimensionally to fin[ru->erefU[ii]] and finnorm[ru->erefU[ii]] that are like R^t_\nu and so need sqrt(gcon[nu,nu]) multiplied on them. This ensures error is non-dimensional (or, really only ^t dimensional)
8774  FTYPE dimfactferr[NPR];
8775  PLOOP(pliter,pl) dimfactferr[pl]=dimfactU[pl]; // default
8776  if(dimtypef==DIMTYPEFCONS){
8777  // assume fin and finnorm are conservative or source (R^t_\nu form)
8778  DLOOPA(ii) dimfactferr[ru->erefU[ii]]=dimfactU[ru->erefU[ii]];
8779  DLOOPA(ii) dimfactferr[ru->eotherU[ii]]=dimfactU[ru->eotherU[ii]];
8780  }
8781  else{
8782  // assume fin and finnorm are primitve (u,vel^i form)
8783  DLOOPA(ii) dimfactferr[ru->erefU[ii]]=1.0/dimfactU[ru->erefU[ii]];
8784  DLOOPA(ii) dimfactferr[ru->eotherU[ii]]=1.0/dimfactU[ru->eotherU[ii]];
8785  }
8786 
8787  // replace finnorm -> finnormnew that's already non-dimensionalized
8788  FTYPE finnormnew[NPR];
8789  // Tds\rho_0 u^t \propto \rho_0 (v/c)^2 or higher \propto \gamma in ultrarel limit
8790  // T^t_t + \rho_0 u^t \propto \rho_0 (v/c)^2 or higher \propto \rho_0\gamma^2 in ultrarel limit
8791  ii=TT;
8792  FTYPE fnormtime = fabs(finnorm[ru->erefU[ii]]*dimfactferr[ru->erefU[ii]]);
8793  FTYPE fnormtimeother = fabs(finnorm[ru->eotherU[ii]]*dimfactferr[ru->eotherU[ii]]);
8794  // T^t_i \propto \rho_0 (v/c)^1 or higher \propto \gamma^2 \rho_0 (v/c) in ultrarel limit
8795  // get spatial contributions as total term so not dominated by small errors in some dimensions
8796  FTYPE fnormspace=0.0; SLOOPA(ii) fnormspace += fabs(finnorm[ru->erefU[ii]]*dimfactferr[ru->erefU[ii]]);
8797  FTYPE fnormspaceother=0.0; SLOOPA(ii) fnormspaceother += fabs(finnorm[ru->eotherU[ii]]*dimfactferr[ru->eotherU[ii]]);
8798 
8799  // need to account for errors when momentum~0
8800 #if(0)
8801 #if(0)
8802  // only kinda applicable for QTYPMHD
8803  FTYPE rhoref=MAX(pp[RHO],piin[RHO]);
8804  FTYPE fnormspace2 = rhoref*prpow(fabs(fnormtime)/rhoref,0.5); // energy term in correct scale with \rho_0(v/c)^1 to get reference in case v\sim 0 NOTE: This assumes rho v term dominates
8805  FTYPE fnormtime2=rhoref*prpow(fabs(fnormspace/rhoref),2.0); // momentum term in correct scale with \rho_0(v/c)^2 in case E\sim 0. NOTE: assumes rho v term dominates.
8806 #else
8807  FTYPE fakevel = MIN(1.0,fnormspace/(SMALL+fnormtime));
8808  FTYPE fnormspace2 = fabs(fnormtime)*fakevel;
8809  // FTYPE fnormtime2 = fabs(fnormspace)/fakevel;
8810  FTYPE fnormtime2 = fnormtime; // no problem with this since now include absolute sum version
8811 #endif
8812  // dualfprintf(fail_file,"fnormspacetime: %g %g %g %g: uu0=%g fakevel=%g\n",fnormspace,fnormspace2,fnormtime,fnormtime2,fabs(uu0[ru->erefU[0]]*dimfactU[ru->erefU[0]]),fakevel);
8813 #else
8814  // These suggest that velocity can be no better than NUMEPSILON*c=NUMEPSILON, but non-rel velocities can be much smaller. But with rad inversion, v^i comes from mixed-up R^t_\mu -- catastrophic cancellation issue. What about MHD?
8815  FTYPE fnormspace2 = fnormtime; // maybe ok SUPERGODMARK -- problem for very small non-rel velocities. __WORKINGONIT__
8816  FTYPE fnormtime2 = fnormtime; // no problem with this since now include absolute sum version
8817  FTYPE fnormspaceother2 = fnormtimeother; // maybe ok SUPERGODMARK -- problem for very small non-rel velocities. __WORKINGONIT__
8818  FTYPE fnormtimeother2 = fnormtimeother; // no problem with this since now include absolute sum version
8819 #endif
8820 
8821 
8822  // YFLx (because can be negative (zero) and so can't use itself only)
8823  PLOOP(pliter,pl){
8824  if(pl==YFL1) finnorm[pl] = fabs(finnorm[pl]) + fabs(finnorm[RHO]);
8825  if(pl==YFL2) finnorm[pl] = fabs(finnorm[pl]) + fabs(finnorm[UU]);
8826  if(pl==YFL3) finnorm[pl] = fabs(finnorm[pl]) + fabs(finnorm[U3]);
8827  if(pl==YFL4) finnorm[pl] = fabs(finnorm[pl]) + fabs(finnorm[URAD0]);
8828  if(pl==YFL5) finnorm[pl] = fabs(finnorm[pl]) + fabs(finnorm[URAD3]);
8829  }
8830 
8831  // now assign
8832  PLOOP(pliter,pl) finnormnew[pl] = finnorm[pl]; // default
8833  ii=TT; finnormnew[ru->erefU[ii]] = fnormtime + fnormtime2;
8834  SLOOPA(ii) finnormnew[ru->erefU[ii]] = fnormspace + fnormspace2;
8835  ii=TT; finnormnew[ru->eotherU[ii]] = fnormtimeother + fnormtimeother2;
8836  SLOOPA(ii) finnormnew[ru->eotherU[ii]] = fnormspaceother + fnormspaceother2;
8837 
8838 
8839  // get non-dimensionalized fin
8840  FTYPE finnew[NPR];
8841  PLOOP(pliter,pl) finnew[pl]=fin[pl]*dimfactferr[pl];
8842 
8843  // get relative errors (keep sign)
8844  // JACLOOPALT(ii,ru->startjac,ru->endjac)
8845  PLOOP(pliter,pl) finreport[pl]=finnew[pl]/fabs(IMPMINABSERROR+fabs(finnormnew[pl]));
8846 
8847  // get absolute error over all (baseitermethod)-iterated terms
8848  // NOTE: the SUBJACJ methods directly use freport[] as needed, not errorabs or passedconv
8849  *errorabs=0.0;
8850  JACLOOPFULLERROR(itermode,jj,ru->startjac,ru->endjac) *errorabs += fabs(finreport[ru->erefU[jj]]); // always full error.
8851 
8852  // completely full relevant error
8853  *errorallabs=0.0; JACLOOPSUPERFULL(pliter,pl,eomtype,baseitermethod,radinvmod) *errorallabs += fabs(finreport[pl]);
8854 
8856  //
8857  // see if passed convergence test criteria
8858  //
8860  passedconv[0]=(*errorabs<convabs);
8861  passedconv[1]=(*errorallabs<convabs);
8862 
8863 
8864 
8865 
8866  // report if passed convergence test
8867  if(passedconv[whicherror]){
8868  prod0dualfprintf(showmessagesheavy,fail_file,"nstep=%ld steppart=%d dt=%g realdt=%g i=%d iter=%d DONE1 for conv=%g : finreport=%g %g %g %g\n",nstep,steppart,dt,realdt,ptrgeom->i,iter,conv,finreport[ru->erefU[0]],finreport[ru->erefU[1]],finreport[ru->erefU[2]],finreport[ru->erefU[3]]);
8869  return(1);
8870  }
8871  else{
8872  // report if didn't pass
8873 #if(PRODUCTION==0)
8874  prod0dualfprintf(showmessagesheavy,fail_file,"POSTFIN (conv=%21.15g): uu: %21.15g %21.15g %21.15g %21.15g : uu0=%21.15g %21.15g %21.15g %21.15g\n",conv,uu[ru->irefU[0]],uu[ru->irefU[1]],uu[ru->irefU[2]],uu[ru->irefU[3]],uu0[ru->irefU[0]],uu0[ru->irefU[1]],uu0[ru->irefU[2]],uu0[ru->irefU[3]]);
8875  PLOOP(pliter,pl) prod0dualfprintf(showmessagesheavy,fail_file,"pl=%d fin=%21.15g finnorm=%21.15g\n",pl,fin[pl],finnorm[pl]);
8876  prod0dualfprintf(showmessagesheavy,fail_file,"nstep=%ld steppart=%d dt=%g i=%d iter=%d : %g %g %g %g\n",nstep,steppart,dt,ptrgeom->i,iter,finreport[ru->erefU[0]],finreport[ru->erefU[1]],finreport[ru->erefU[2]],finreport[ru->erefU[3]]);
8877 #endif
8878  return(0);
8879  }
8880 
8881  return(0);
8882 }
8883 
8884 
8885 #define JDIFFONESIDED 0
8886 #define JDIFFCENTERED 1
8887 
8888 
8889 
8892 static int get_implicit_iJ(int allowbaseitermethodswitch, int failreturnallowableuse, int showmessages, int showmessagesheavy, int allowlocalfailurefixandnoreport, int *eomtypelocal, int whichcap, int itermode, int *baseitermethod, FTYPE fracenergy, FTYPE dissmeasure, FTYPE impepsjac, FTYPE trueimptryconv, FTYPE trueimptryconvabs, FTYPE trueimpallowconvabs, int trueimpmaxiter, int iter, FTYPE errorabs, FTYPE errorallabs, int whicherror, int dimtypef, FTYPE *dimfactU, FTYPE *Uiin, FTYPE *uu, FTYPE *uup, FTYPE *uu0, FTYPE *piin, FTYPE *pp, FTYPE *ppp, FTYPE fracdtG, FTYPE realdt, struct of_geom *ptrgeom, struct of_state *q, FTYPE *f1, FTYPE *f1norm, FTYPE (*iJ)[NPR], int *nummhdinvsreturn, struct of_method *mtd, struct of_refU *ru)
8893 {
8894  int ii,jj;
8895  struct of_state qjac=*q; // not required as input, but set as output.
8896 
8897  int eomtypelocallocal=*eomtypelocal; // default
8898 
8899  int JDIFFTYPE;
8900 #if(DOPERF==0)
8901  if(IMPPTYPE(mtd->implicititer)){
8902  // with mtd->implicititer==QTYPMHD, no longer expensive so can do JDIFFCENTERED
8903  // choose:
8904  // if(itermode==ITERMODENORMAL) JDIFFTYPE=JDIFFCENTERED; // and only helps rarely and makes 2X slower.
8905  // else if(itermode==ITERMODESTAGES) JDIFFTYPE=JDIFFONESIDED; // seems accurate enough
8906  if(itermode==ITERMODESTAGES) JDIFFTYPE=JDIFFCENTERED; // and only helps rarely and makes 2X slower.
8907  else if(itermode==ITERMODENORMAL) JDIFFTYPE=JDIFFONESIDED; // seems accurate enough
8908  // JDIFFTYPE=JDIFFCENTERED; // and only helps rarely and makes 2X slower.
8909  // JDIFFTYPE=JDIFFONESIDED; // and only helps rarely and makes 2X slower.
8910  }
8911  else{
8912  JDIFFTYPE=JDIFFONESIDED;
8913  }
8914 #else
8915  JDIFFTYPE=JDIFFONESIDED; // avoid expense
8916 #endif
8917 
8918  // ensure uu and pp don't get modified by del-shifts to get Jacobian, which can change primitives to order unity at high radiation gamma
8919  FTYPE uujac[NPR],ppjac[NPR];
8920  FTYPE uujacalt[NPR],ppjacalt[NPR];
8921  int pliter,pl;
8922 
8923 
8925  //
8926  // Setup which quantitiy iterating
8927  // Scale-out dimensional stuff before forming predel
8928  //
8930  // for scaling del's norm. Applies to time component to make as if like space component.
8931  FTYPE upitoup0[NPR], upitoup0U[NPR], upitoup0P[NPR];
8932  FTYPE x[NPR],xp[NPR],xjac[2][NPR],xjacalt[NPR];
8933  FTYPE velmomscale;
8934 
8935  // FTYPE dimfactU[NPR];
8936  // PLOOP(pliter,pl) dimfactU[pl]=1.0; // default
8937  // DLOOPA(jjdim) dimfactU[UU+jjdim]=dimfactU[URAD0+jjdim]=sqrt(fabs(ptrgeom->gcon[GIND(jjdim,jjdim)]));
8938  // SLOOPA(jjdim) dimfactU[B1+jjdim-1] = 1.0/dimfactU[U1+jjdim-1];
8939 
8940  // U
8941  // \rho_0 u^t * sqrt(-1/g^{tt}) and most things will be scalars like S u^t as well
8942  // R^t_nu * sqrt(g^{ii}/g^{tt}) = R^t_orthonu
8943  PLOOP(pliter,pl) upitoup0U[pl] = dimfactU[pl]*ptrgeom->alphalapse ;
8944 
8945  // P
8946  PLOOP(pliter,pl) upitoup0P[pl] = 1.0; // comoving quantities
8947  // v^i / sqrt(g^{ii}) = vortho^i
8948  SLOOPA(jj) upitoup0P[UU+jj] =upitoup0P[URAD0+jj] = 1.0/dimfactU[UU+jj];
8949 
8950 
8952  //
8953  // use uucopy as uu instead of modifying uu in case uu needs adjusting
8954  //
8956  FTYPE uucopy[NPR],ppcopy[NPR];
8957  PLOOP(pliter,pl){
8958  uucopy[pl]=uu[pl];
8959  ppcopy[pl]=pp[pl];
8960  }
8961 
8962 #define MAXSIGN(x,y) (fabs(x)>fabs(y) ? (x) : (y))
8963 #define MINSIGN(x,y) (fabs(x)<fabs(y) ? (x) : (y))
8964 
8966  //
8967  // check whether origin point is too small relative to uu0
8968  //
8970  // JACLOOP(jj,ru->startjac,ru->endjac){
8971  DLOOPA(jj){ // so all related U's are changed.
8972  // if(fabs(uucopy[ru->irefU[jj]])<100.0*NUMEPSILON*fabs(uu0[ru->irefU[jj]])){
8973  // then set "floor" on uucopy used for Jacobian because otherwise uu is unresolved by f_implicit() error function
8974  uucopy[ru->irefU[jj]]=MAXSIGN(MAXSIGN(uucopy[ru->irefU[jj]],100.0*NUMEPSILON*uu0[ru->irefU[jj]]),100.0*NUMEPSILON*uup[ru->irefU[jj]]);
8975  // modify associated pp in reasonable way in case P method since otherwise error will be unresolved using that p associated with that uu
8976  // only modify primitives associated with those conserved quantities (i.e. gas uu and pp or rad uu and pp)
8977  ppcopy[ru->irefU[jj]]=MAXSIGN(MAXSIGN(ppcopy[ru->irefU[jj]],100.0*NUMEPSILON*piin[ru->irefU[jj]]),100.0*NUMEPSILON*ppp[ru->irefU[jj]]);
8978  }
8979 
8980 
8981 
8983  //
8984  // setup origin point for difference
8985  //
8987 
8988  // U
8989  if(IMPUTYPE(mtd->implicititer)){
8990  PLOOP(pliter,pl) x[pl]=uucopy[pl];
8991  PLOOP(pliter,pl) xp[pl]=uup[pl];
8992  PLOOP(pliter,pl) xjac[0][pl]=xjac[1][pl]=xjacalt[pl]=uucopy[pl];
8993  PLOOP(pliter,pl) upitoup0[pl] = upitoup0U[pl];
8994  // velmomscale is set such that when (e.g.) T^t_i is near zero, we use T^t_t as reference since we consider T^t_i/T^t_t to be velocity scale that is up to order unity.
8995  // velmomscale=prpow(fabs(x[ru->irefU[TT]]*upitoup0[ru->irefU[TT]]),1.5);
8996  velmomscale=prpow(fabs(x[ru->irefU[TT]]*upitoup0[ru->irefU[TT]]),1.0); // __WORKINGONIT__
8997  }
8998  // P
8999  else if(IMPPTYPE(mtd->implicititer)){
9000  PLOOP(pliter,pl) x[pl]=ppcopy[pl];
9001  PLOOP(pliter,pl) xp[pl]=ppp[pl];
9002  PLOOP(pliter,pl) xjac[0][pl]=xjac[1][pl]=xjacalt[pl]=ppcopy[pl];
9003  PLOOP(pliter,pl) upitoup0[pl] = upitoup0P[pl];
9004  // for velocity, assume ortho-scale is order unity (i.e. v=1.0*c)
9005  // velmomscale=1.0; // reference scale considered to be order unity KORALTODO: Not sure if should use something like T^t_i/T^t_t with denominator something more non-zero-ish.
9006  if(IMPMHDTYPE(mtd->implicititer)) velmomscale=MAX(SMALL,sqrt(fabs(x[UU])/MAX(ppp[RHO],ppcopy[RHO]))); // u_g/\rho_0\propto (v/c)^2, so this gives \propto (v/c) . Leads to more problems for RADTUBE
9007  else velmomscale=1.0; // __WORKINGONIT__
9008 
9009  // limit
9010  velmomscale=MIN(1.0,velmomscale);
9011 
9012  // velmomscale=1.0; // __WORKINGONIT__
9013  }
9014 
9016  //
9017  // form pre-del
9018  //
9020  FTYPE delspace,deltime,predel[NDIM];
9021 
9022  // get everything in terms of quasi-orthonormal quantities
9023  FTYPE vsqnorm=0.0;
9024  JACLOOPALT(jj,ru->startjac,ru->endjac){
9025  predel[jj] = fabs(x[ru->irefU[jj]]*upitoup0[ru->irefU[jj]]);
9026  if(ru->irefU[jj]==UU || ru->irefU[jj]==URAD0 || IMPUTYPE(mtd->implicititer)){
9027  // below makes sense because U and ferr are linear in x and same dimensional units
9028  // TT term (e.g. u_g) can be too small primitive or otherwise, so use maximum of ferr, uu, and x.
9029  // This avoids issue with Jacobian giving J44[0][0]=0 so that can't iterate u_g because u_g itself is very small.
9030  predel[jj] = MAX(predel[jj],fabs(uup[ru->irefU[jj]]*upitoup0U[ru->irefU[jj]]));
9031  predel[jj] = MAX(predel[jj],fabs(uu0[ru->irefU[jj]]*upitoup0U[ru->irefU[jj]]));
9032  // using error function to normalize is too risky since error is not linear in irefU. e.g., error is not linear in u_g.
9033  // predel[jj] = MAX(predel[jj],fabs(f1[ru->erefU[jj]]*upitoup0U[ru->erefU[jj]]));
9034  // predel[jj] = MAX(predel[jj],fabs(f1norm[ru->erefU[jj]]*upitoup0U[ru->erefU[jj]]));
9035  }
9036  else{
9037  // if primitive velocity, then different units than conserved or error function that have energy density scale
9038  }
9039 
9040  if((jj==1 || jj==2 || jj==3) && IMPPTYPE(mtd->implicititer)){
9041  // v^2 quasi-orthonormal
9042  vsqnorm += fabs(x[ru->irefU[jj]]*upitoup0[ru->irefU[jj]])*fabs(x[ru->irefU[jj]]*upitoup0[ru->irefU[jj]]);
9043  }
9044  }
9045  // limit
9046  vsqnorm=MIN(1.0,vsqnorm);
9047 
9049  // form delspace that absorbs all spatial values into a single dimensionless scale to avoid one dimensions smallness causing issues.
9050  // KORALTODO: Maybe causes problems if Jacobian becomes singular because no change in small velocity-momentum values when should be change. But can't resolve it really, so should be ok.
9051  // NOTE: If JACLOOPALT doesn't include momentum, the below doesn't hurt.
9053 
9054  // Add all spatial terms in quasi-orthonormal way
9055  // Also add (u_g)^{1/2} \propto \rho_0(v/c)
9056  delspace=0.0; SLOOPA(jj) delspace = MAX(delspace,MAX(fabs(predel[jj]) , velmomscale )); // dimensionless-ortho
9057 
9058  //__WORKINGONIT__: Needs to improve and be more general
9059  if(IMPPMHDTYPE(mtd->implicititer)){
9060  // u_g goes like \rho_0 v^2
9061  jj=TT; deltime = MAX(fabs(predel[jj]),MAX(ppp[RHO],ppcopy[RHO])*vsqnorm); // __WORKINGONIT__ : Leads to more problems for RADTUBE
9062  //jj=TT; deltime = fabs(predel[jj]);
9063  }
9064  else if(IMPPTYPE(mtd->implicititer)){
9065  jj=TT; deltime = fabs(predel[jj]);
9066  }
9067  else{
9068  jj=TT; deltime = fabs(predel[jj]);
9069  }
9070 
9072  // back to actual spatial dimension-space scale for application to x and xjac
9073  SLOOPA(jj) predel[jj] = delspace/upitoup0[ru->irefU[jj]];
9074 
9075 
9076 
9077  // back to actual time dimension scale
9078  // NOTE: If JACLOOPALT doesn't include energy, the below doesn't hurt.
9079  jj=TT;
9080  predel[jj] = predel[jj]/upitoup0[ru->irefU[jj]];
9081 
9082 
9083 
9084  FTYPE J[NPR][NPR];
9085  FTYPE f2[2][NPR],f2norm[2][NPR],f2report[2][NPR],errorabsf2[NUMERRORTYPES];
9086  set_array(errorabsf2,NUMERRORTYPES,MPI_FTYPE,BIG);
9087 
9088  // set defaults for one-sided case.
9089  if(JDIFFTYPE==JDIFFONESIDED){
9090  PLOOP(pliter,pl) f2[0][pl]=f1[pl];
9091  // Note that xjac[0] already set correctly.
9092  }
9093 
9094  int failreturn;
9095  int fulljaciter=0;
9096  FTYPE FRACIMPEPSCHANGE=0.1;
9097  FTYPE del;
9098  FTYPE IMPEPSSTART=impepsjac;
9099  while(1){ // ensuring that Jacobian is non-singular if only because del too small (and then if singular, increase del)
9100 
9101  FTYPE localIMPEPS=IMPEPSSTART; // start with fresh del
9102 
9103  JACLOOP(jj,ru->startjac,ru->endjac){
9104 
9105  int sided,signside;
9106  int numsides=2; // fixed at 2
9107  for(sided=0;sided<numsides;sided++){
9108  if(JDIFFTYPE==JDIFFONESIDED && sided==0) continue;
9109 
9110  // want chosen energy to have controlled drop, so other energy rises and doesn't drop out of bounds
9111  if(IMPPTYPE(mtd->implicititer)){
9112  if(sided==1) signside=-1.0;
9113  else signside=+1.0;
9114  }
9115  else{
9116  if(sided==1) signside=+1.0;
9117  else signside=-1.0;
9118  }
9119 
9120  while(1){
9121 
9122  // when |irefU[0]|>>|irefU[1]|, then can't get better than machine error on irefU[0], not irefU[1], so using small del just for irefU[1] makes no sense, so avoid above
9123  del = localIMPEPS*predel[jj];
9124 
9125 
9126  // origin point
9127  PLOOP(pliter,pl) xjac[sided][pl]=xjacalt[pl]=x[pl];
9128 
9129 
9130  if(JDIFFTYPE==JDIFFONESIDED && sided==1){
9131  if(*baseitermethod==QTYPMHD || *baseitermethod==QTYPRAD){
9132  // then choose direction so that decrease u_g and decreases magnitude of \gamma
9133  if(x[ru->irefU[jj]]>0.0){
9134  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del;
9135  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del;
9136  }
9137  else{
9138  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del;
9139  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del;
9140  }
9141  }
9142  else if(*baseitermethod==QTYURAD){
9143  // ensure R^t_t decreases so Erf doesn't drop out
9144  if(x[ru->irefU[jj]]>0.0){
9145  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del*(jj==TT ? -1.0 : 1.0);
9146  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del*(jj==TT ? -1.0 : 1.0);
9147  }
9148  else{
9149  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del*(jj==TT ? -1.0 : 1.0);
9150  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del*(jj==TT ? -1.0 : 1.0);
9151  }
9152  }
9153  else if(*baseitermethod==QTYUMHD){
9154  // STILL for this method, ensure R^t_t decreases so Erf doesn't drop out
9155  if(x[ru->irefU[jj]]>0.0){
9156  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del*(jj==TT ? -1.0 : 1.0);
9157  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del*(jj==TT ? -1.0 : 1.0);
9158  }
9159  else{
9160  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del*(jj==TT ? -1.0 : 1.0);
9161  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del*(jj==TT ? -1.0 : 1.0);
9162  }
9163  }
9164  else{
9165  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del;
9166  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del;
9167  }
9168  }
9169  else{
9170  // offset xjac (KORALTODO: How to ensure this doesn't have machine precision problems or is good enough difference?)
9171  xjac[sided][ru->irefU[jj]]=x[ru->irefU[jj]] + signside*del; // KORALNOTE: Not sure why koral was using uup or xp here. Should use x (or uu or pp) because as updated from f_implicit() and uup or ppp for xp hasn't been set yet, so not consistent with desired jacobian or ferr for Newton step.
9172  xjacalt[ru->irefU[jj]]=x[ru->irefU[jj]] - signside*del;
9173  // dualfprintf(fail_file,"NEW: jj=%d del=%g xjac=%g x=%g\n",jj,del,xjac[sided][ru->irefU[jj]],x[ru->irefU[jj]]);
9174  }
9175 
9176  // set uujac and ppjac using xjac
9177  if(IMPUTYPE(mtd->implicititer)){
9178  PLOOP(pliter,pl){
9179  uujac[pl]=xjac[sided][pl];
9180  uujacalt[pl]=xjacalt[pl];
9181  ppjac[pl]=ppjacalt[pl]=ppcopy[pl];
9182  }
9183  }
9184  else if(IMPPTYPE(mtd->implicititer)){
9185  PLOOP(pliter,pl){
9186  uujac[pl]=uujacalt[pl]=uucopy[pl];
9187  ppjac[pl]=xjac[sided][pl];
9188  ppjacalt[pl]=xjacalt[pl];
9189  }
9190  if(FORCEJDIFFNOCROSS){
9191  // constrain that which enters jacobian
9192  int subjj;
9193  JACLOOP(subjj,ru->startjac,ru->endjac){
9194  pl=ru->irefU[subjj];
9195  FTYPE ppmin=100.0*NUMEPSILON*fabs(predel[subjj]);
9196  // FTYPE umin=calc_PEQ_ufromTrho(TEMPMIN,ppjac[RHO]);
9197  //
9198  if(POSPL(pl)){
9199  if(xjac[sided][pl]<ppmin && x[pl]>0.0){
9200  xjac[sided][pl]=ppmin;
9201  prod0dualfprintf(debugfail>=3,fail_file,"Got 1: sided=%d\n",sided);
9202  }
9203  else if(xjac[sided][pl]>-ppmin && x[pl]<0.0){
9204  xjac[sided][pl]=-ppmin;
9205  prod0dualfprintf(debugfail>=3,fail_file,"Got 2: sided=%d\n",sided);
9206  }
9207  // now fix ppjac
9208  ppjac[pl]=xjac[sided][pl];
9209  }// end if supposed to normally be positive value quantity
9210  }
9211  }
9212  }
9213 
9214 
9215  // get dUresid for this offset xjac
9216  int whichcall=FIMPLICITCALLTYPEJAC;
9217  eomtypelocallocal=*eomtypelocal; // re-default
9218  int fakeiter=iter;
9219  int fakef1iter=-1;
9220  int radinvmod=0; // ignore, assume normal error check will be where this information is used.
9221  // dualfprintf(fail_file,"iJ calls f_implicit: iter=%d\n",iter);
9222  int goexplicitfake; // in Jacobian, so don't try to abort.
9223  int convreturnf2;
9224  int whichcapnew=CAPTYPEFIX2; // so Erf stays well-defined even if innaccurate a bit. So J stays well-defined so iJ doesn't nan-out
9225  // PLOOP(pliter,pl) dualfprintf(fail_file,"pl=%d ppjac=%21.15g uu0=%21.15g uujac=%21.15g\n",pl,ppjac[pl],uu0[pl],uujac[pl]);
9226  FTYPE tautotmaxreturn;
9227  failreturn=f_implicit(allowbaseitermethodswitch, fakeiter,fakef1iter,failreturnallowableuse, whichcall,localIMPEPS,showmessages,showmessagesheavy, allowlocalfailurefixandnoreport, &eomtypelocallocal, whichcapnew,itermode, baseitermethod, fracenergy, dissmeasure, &radinvmod, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, realdt, dimtypef, dimfactU, ppjacalt, ppjac,piin,uujacalt, Uiin,uu0,uujac,fracdtG*realdt,ptrgeom,&qjac,f2[sided],f2norm[sided],f2report[sided], &goexplicitfake, &errorabsf2[0], &errorabsf2[1], whicherror, &convreturnf2, nummhdinvsreturn, &tautotmaxreturn, mtd, ru);
9228  if(failreturn){ // __WORKINGONIT__: Noticed if ==1 (radinv failure), then hits this and tries again. Maybe costly, and maybe not required with CAPTYPEFIX2 used at least for PMHD,PRAD methods.
9229  prod0dualfprintf(showmessages&& debugfail>=2,fail_file,"f_implicit for f2 failed: jj=%d. Trying smaller localIMPEPS=%g (giving del=%g) to %g\n",jj,localIMPEPS,del,localIMPEPS*FRACIMPEPSCHANGE);
9230  localIMPEPS*=FRACIMPEPSCHANGE;
9231  // try making smaller until no error, unless doesn't work out
9232  // see if will be able to resolve differences
9233  int baddiff = fabs(xjac[sided][ru->irefU[jj]]-x[ru->irefU[jj]])/(fabs(xjac[sided][ru->irefU[jj]])+fabs(x[ru->irefU[jj]])) < 10.0*NUMEPSILON;
9234  if(localIMPEPS<10.0*NUMEPSILON || baddiff){
9235  // then probably can't resolve difference due to too small
9236  if(failreturnallowableuse>=UTOPRIMGENWRAPPERRETURNFAILRAD){
9237  prod0dualfprintf(debugfail>=2,fail_file,"Bad error: f_implicit for f2 failed: jj=%d with localIMPEPS=%g (giving del=%g)\n",jj,localIMPEPS,del);
9238  return(1); // can't go below machine precision for difference else will be 0-0 and no reversion to do.
9239  }
9240  else{
9241  // instead of failing, allow radiation error, and restart process
9242  failreturnallowableuse=UTOPRIMGENWRAPPERRETURNFAILRAD; // just changes value in this function only. Assume that once do this, applies to all further terms in Jacobian.
9243  localIMPEPS=IMPEPSSTART; // start with fresh del
9244  }
9245  }
9246  }// end if failreturn!=0
9247  else{
9248  // didn't fail
9249  break;
9250  }
9251  }// end while(1), checking if ferr failed due to (e.g.) inversion issue.
9252  }// end sided=0,1
9253 
9254 
9255  // get Jacobian
9256  JACLOOP(ii,ru->startjac,ru->endjac) J[ru->erefU[ii]][ru->irefU[jj]]=(f2[1][ru->erefU[ii]] - f2[0][ru->erefU[ii]])/(xjac[1][ru->irefU[jj]]-xjac[0][ru->irefU[jj]]);
9257 
9258  //JACLOOP(ii,ru->startjac,ru->endjac) dualfprintf(fail_file,"NEW: ii=%d jj=%d J=%g : %g %g : %g %g\n",ii,jj,J[ru->erefU[ii]][ru->irefU[jj]], f2[1][ru->erefU[ii]],f2[0][ru->erefU[ii]],xjac[1][ru->irefU[jj]],xjac[0][ru->irefU[jj]]);
9259 
9260 
9261 #if(PRODUCTION==0)
9262  // debug info
9263  if(debugfail>=2){
9264  int badcond=0;
9265  JACLOOP(ii,ru->startjac,ru->endjac){
9266  if(showmessagesheavy || !isfinite(J[ru->erefU[ii]][ru->irefU[jj]])|| fabs(J[ru->erefU[jj]][ru->irefU[jj]])<SMALL ) {
9267  badcond++;
9268  }
9269  }
9270  if(badcond){
9271  JACLOOP(ii,ru->startjac,ru->endjac){
9272  dualfprintf(fail_file,"JISNAN: iter=%d startjac=%d endjac=%d ii=%d jj=%d irefU[jj]=%d erefU[ii]=%d : xjac[0]: %21.15g : xjac[1]: %21.15g : x=%21.15g (del=%21.15g localIMPEPS=%21.15g) : f2[0]=%21.15g f2[1]=%21.15g J=%21.15g : f2norm[0]=%21.15g f2norm[1]=%21.15g\n",
9273  iter,ru->startjac,ru->endjac,
9274  ii,jj,ru->irefU[jj],ru->erefU[ii],
9275  xjac[0][ru->irefU[jj]],
9276  xjac[1][ru->irefU[jj]],
9277  x[ru->irefU[jj]],
9278  del,localIMPEPS,
9279  f2[0][ru->erefU[ii]],f2[1][ru->erefU[ii]],J[ru->erefU[ii]][ru->irefU[jj]],
9280  f2norm[0][ru->erefU[ii]],f2norm[1][ru->erefU[ii]]
9281  );
9282  }
9283  JACLOOP(ii,ru->startjac,ru->endjac){
9284  dualfprintf(fail_file,"NEW: ii=%d jj=%d J=%21.15g : %21.15g %21.15g : %21.15g %21.15g\n",ii,jj,J[ru->erefU[ii]][ru->irefU[jj]], f2[1][ru->erefU[ii]],f2[0][ru->erefU[ii]],xjac[1][ru->irefU[jj]],xjac[0][ru->irefU[jj]]);
9285  }
9286  PLOOP(pliter,pl) dualfprintf(fail_file,"JISNAN2: pl=%d ppjac=%21.15g uu0=%21.15g uujac=%21.15g\n",pl,ppjac[pl],uu0[pl],uujac[pl]);
9287  JACLOOP(ii,ru->startjac,ru->endjac) dualfprintf(fail_file,"ii=%d uucopy=%21.15g uu=%21.15g\n",ii,uucopy[ru->irefU[ii]],uu[ru->irefU[ii]]);
9288  }//end if badcond>0
9289  }//end debug
9290 #endif
9291 
9292  }// end JACLOOP
9293 
9294 
9295 
9296 
9297 #if(PRODUCTION==0)
9298  if(showmessagesheavy){
9299  dualfprintf(fail_file,"POSTJAC: x: %21.15g %21.15g %21.15g %21.15g : x=%21.15g %21.15g %21.15g %21.15g\n",x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]],x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]]);
9300  int iii,jjj;
9301  JACLOOP2D(iii,jjj,ru->startjac,ru->endjac) dualfprintf(fail_file,"J[%d][%d]=%21.15g\n",iii,jjj,J[ru->erefU[iii]][ru->irefU[jjj]]);
9302  }
9303 #endif
9304 
9305 
9306 
9307 
9309  //
9310  //invert Jacobian
9311  //
9313 
9314 
9315  // copy over matrix to sub (up to) 4x4 version
9316  FTYPE Jsub[NDIM][NDIM];
9317  FTYPE iJsub[NDIM][NDIM];
9318  JACLOOP2D(ii,jj,ru->startjac,ru->endjac) Jsub[ii][jj]=J[ru->erefU[ii]][ru->irefU[jj]];
9319 
9320  if(ru->endjac-ru->startjac+1==NDIM){
9321  // inverse *and* transpose index order, so J[erefU][irefU] -> iJ[irefU][erefU]
9322  failreturn=inverse_44matrix(Jsub,iJsub);
9323  }
9324  else if(ru->endjac-ru->startjac+1==NDIM-1){ // probably momentum only
9325  // inverse *and* transpose index order, so J[erefU][irefU] -> iJ[irefU][erefU]
9326  failreturn=inverse_33matrix(ru->startjac,ru->endjac,Jsub,iJsub);
9327  }
9328  else if(ru->endjac-ru->startjac+1==1){ // probably energy only
9329  // inverse *and* transpose index order, so J[erefU][irefU] -> iJ[irefU][erefU]
9330  failreturn=inverse_11matrix(ru->startjac,ru->endjac,Jsub,iJsub);
9331  }
9332 
9333  // copy back inverse matrix from sub-version
9334  JACLOOP2D(ii,jj,ru->startjac,ru->endjac){
9335  iJ[ru->irefU[ii]][ru->erefU[jj]]=iJsub[ii][jj]; // iJsub has been transposed from input Jsub, so iJsub[irefU][erefU]
9336  // dualfprintf(fail_file,"NEW: ii=%d jj=%d iJ=%g\n",ii,jj,iJ[ru->irefU[ii]][ru->erefU[jj]]);
9337  }
9338 
9339 
9340  if(failreturn){
9341 
9342 
9343 #if(PRODUCTION==0)
9344  // debug:
9345  if(debugfail>=2){
9346  dualfprintf(fail_file,"Tried to invert Jacobian with %d %d %d %d : %g %g %g : %g %g %g : %d %d : %g %g : %d : %g %g\n",*eomtypelocal, whichcap, itermode, *baseitermethod, fracenergy, dissmeasure, impepsjac, trueimptryconv, trueimptryconvabs, trueimpallowconvabs, trueimpmaxiter, iter, errorabs, errorallabs, whicherror,fracdtG,realdt);
9347  PLOOP(pliter,pl) dualfprintf(fail_file,"1Tried: pl=%d Uiin=%g uu=%g uup=%g uu0=%g piin=%g pp=%g ppp=%g f1=%g f1norm=%g\n", pl, Uiin[pl], uu[pl], uup[pl], uu0[pl], piin[pl], pp[pl], ppp[pl], f1[pl], f1norm[pl]);
9348  JACLOOP2D(ii,jj,ru->startjac,ru->endjac){
9349  dualfprintf(fail_file,"2Tried: ii=%d jj=%d (%d %d) : j=%g iJ=%g\n",ii,jj,ru->startjac,ru->endjac,Jsub[ii][jj],iJsub[ii][jj]);
9350  }
9351  }
9352 #endif
9353 
9354  // act on failure?
9355 
9356  }// end if failreturn!=0
9357 
9358 
9359 
9361  //
9362  // check if Jacobian inversion was successful
9363  //
9365  if(failreturn){
9366  // try increasing localIMPEPS
9367  IMPEPSSTART/=FRACIMPEPSCHANGE;
9368  int condnotdiff;
9369  condnotdiff=IMPEPSSTART > MAXIMPEPS;
9370 
9371  if(condnotdiff){ // KORALTODO: But error relative to x needs to be accounted for!
9372 
9373 #if(PRODUCTION==0)
9374  if(debugfail>=2) dualfprintf(fail_file,"f_implicit for f2 failed to be different enough from f1 and gave singular Jacobian: IMPEPSSTART=%g (giving del=%g)\n",IMPEPSSTART,del);
9375  if(debugfail>=2 || showmessagesheavy){
9376  dualfprintf(fail_file,"POSTJAC1: x: %21.15g %21.15g %21.15g %21.15g : x=%21.15g %21.15g %21.15g %21.15g\n",x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]],x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]]);
9377  int iii,jjj;
9378  DLOOP(iii,jjj) dualfprintf(fail_file,"Jsub[%d][%d]=%21.15g\n",iii,jjj,Jsub[iii][jjj]);
9379  }
9380 #endif
9381 
9382  return(1); // can't expect good derivative above ~0.3, so just return as failure of implicit method.
9383  }
9384  else{
9385 
9386 #if(PRODUCTION==0)
9387  if(debugfail>=2) dualfprintf(fail_file,"inverse_44matrix(J,iJ) failed with eomtypelocallocal=%d, trying IMPEPSSTART=%g :: ijk=%d %d %d\n",eomtypelocallocal,IMPEPSSTART,ptrgeom->i,ptrgeom->j,ptrgeom->k);
9388  if(debugfail>=2 || showmessagesheavy){
9389  dualfprintf(fail_file,"POSTJAC2: x: %21.15g %21.15g %21.15g %21.15g : x=%21.15g %21.15g %21.15g %21.15g\n",x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]],x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]]);
9390  int iii,jjj;
9391  DLOOPA(iii) dualfprintf(fail_file,"predel[%d]=%21.15g\n",iii,predel[iii]);
9392  DLOOP(iii,jjj) dualfprintf(fail_file,"Jsub[%d][%d]=%21.15g\n",iii,jjj,Jsub[iii][jjj]);
9393  }
9394 #endif
9395 
9396  }
9397  }// end if failred to invert J
9398  else break; // good Jacobian
9399 
9400  // check if trying too many times to get Jacobian
9401  fulljaciter++;
9402  if(fulljaciter>MAXJACITER){
9403  // this is a catch in case bouncing back and forth between singular Jac and no inversion for P(U) to get f2
9404 
9405 #if(PRODUCTION==0)
9406  if(debugfail>=2) dualfprintf(fail_file,"Failed to get inverse Jacobian with fulljaciter=%d with IMPEPSSTART=%g (giving del=%g)\n",fulljaciter,IMPEPSSTART,del);
9407  if(debugfail>=2 || showmessagesheavy){
9408  dualfprintf(fail_file,"POSTJAC3: x: %g %g %g %g : x=%g %g %g %g\n",x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]],x[ru->irefU[0]],x[ru->irefU[1]],x[ru->irefU[2]],x[ru->irefU[3]]);
9409  int iii,jjj;
9410  DLOOP(iii,jjj) dualfprintf(fail_file,"Jsub[%d][%d]=%g\n",iii,jjj,Jsub[iii][jjj]);
9411  }
9412 #endif
9413 
9414  return(1);
9415  }
9416  }// end over ensuring Jacobian is non-singular for the given del
9417 
9418 
9419 
9420  return(0);
9421 
9422 }
9423 
9424 
9425 
9426 
9427 
9428 
9429 
9430 
9431 
9432 
9433 
9434 
9435 
9436 
9437 
9438 
9439 
9440 
9441 
9442 
9443 
9445 static void get_dtsub(int method, FTYPE *pr, struct of_state *q, FTYPE *Ui, FTYPE *Uf, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gdpl, FTYPE chi, FTYPE *Gdplabs, struct of_geom *ptrgeom, FTYPE *dtsub)
9446 {
9447  int jj;
9448  int pliter,pl;
9449  FTYPE idtsub0,idtsub;
9450  //
9451  FTYPE Umhd,Urad,Gmhd,Grad,iUmhd,iUrad;
9452  //
9453  FTYPE idtsubs,idtsubt;
9454  FTYPE idtsubmhd,idtsubrad;
9455  FTYPE Usmhd,Usrad,Gsmhd,Gsrad,iUsmhd,iUsrad;
9456  FTYPE Utmhd,Utrad,Gtmhd,Gtrad,iUtmhd,iUtrad;
9457  FTYPE Gddtpl[NPR];
9458 
9459 
9460  if(REMOVERESTMASSFROMUU!=2){
9461  dualfprintf(fail_file,"get_dtsub() assumes removed rest mass from UU so can compare G and U[UU]\n");
9462  myexit(9285345);
9463  }
9464 
9465  // KORALTODO: If Umhd is very small and dynamically unimportant, should probably ignore trying to subcycle, but at least limit number of sub-cycles. May be more of a problem when deal with MHD in force-free magnetosphere.
9466 
9467  // NOTE: The timestep does not fllow NR1992 S19.2L on diffusion equation step size. That applies if diffusion was part of flux calculation, not source term. And it applies to the radiative velocity limiter for the advection's effective wave speed.
9468  // The relevant NR1992 is S16.6L on stiff source terms.
9469 
9470  // get G*dt that can be compared to Umhd or Urad
9471  int isexplicit=1;
9472  FTYPE realdt=compute_dt(isexplicit,CUf, CUimp,dt);
9473 
9474  // choose if using actual 4-force or absolutified 4-force
9475  if(0){
9476  PLOOP(pliter,pl) Gddtpl[pl] = Gdpl[pl]*realdt;
9477  }
9478  else{
9479  PLOOP(pliter,pl) Gddtpl[pl] = Gdplabs[pl]*realdt;
9480  }
9481 
9482 
9484  //
9485  // get updated uu from dUother in case leads to different result
9486  FTYPE U0[NPR];
9487  FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
9488  PLOOP(pliter,pl) U0[pl]=UFSET(CUf,dt,Ui[pl],Uf[pl],dUother[pl],0.0,dUnongeomall);
9489 
9490  // PLOOP(pliter,pl) dualfprintf(fail_file,"pl=%d U0=%g realdt=%g dt=%g Ui=%g Uf=%g dUother=%g\n",pl,U0[pl],realdt,dt,Ui[pl],Uf[pl],dUother[pl]);
9491 
9492 
9493 
9494  // get original U
9495  FTYPE U[NPR];
9496  PLOOP(pliter,pl) U[pl]=Ui[pl];
9497 
9498 
9499 
9500 
9501  // get smallest timestep for stiff source terms of 8 equations with a single source term vector.
9502  // Based upon NR 16.6.6L with removal of factor of two
9503  if(method==TAUSUPPRESS){
9504  // KORALTODO: \tau suppression not general enough because G\propto R\tau + \gamma R \tau + \gamma B, and further, this assumes T\sim R. If T<<R, then suppression by \tau won't be enough to treat stiffness effect on fluid's T.
9505  // dR^t_t/R^t_t \sim c \gamma_{fluid} \chi dt = \sim c \gamma_{fluid} \tau dt/dx , but might as well just use first version
9506 
9507 
9508  if(0){
9509  // Older Olek method
9510  // use approximate dt along each spatial direction. chi is based in orthonormal basis
9511  // get maximum \tau for all relevant directions
9512  FTYPE dxortho[NDIM],tautotdir[NDIM];
9513  SLOOPA(jj) dxortho[jj] = (dx[jj]*sqrt(fabs(ptrgeom->gcov[GIND(jj,jj)])));
9514  // KORALTODO: Should this only depend upon kappa and not kappaes? Stiffness in source term comes from full chi, so seems to be full chi.
9515  SLOOPA(jj) tautotdir[jj] = chi * dxortho[jj];
9516  // only include relevant directions
9517  FTYPE taumax=SMALL+MAX(MAX(tautotdir[1]*N1NOT1,tautotdir[2]*N2NOT1),tautotdir[3]*N3NOT1);
9518 
9519  idtsub0=taumax/realdt;
9520  }
9521  else{
9522  FTYPE ratchangeRtt=calc_approx_ratchangeRtt(q, chi, realdt);
9523 
9524  idtsub0 = ratchangeRtt/realdt; // if ratchange=1, then in principle right at edge of big change.
9525 
9526  // dualfprintf(fail_file,"ucon0=%g chi=%g ratchangeRtt=%g idtsub=%g\n",ucon0,chi,ratchangeRtt,idtsub0);
9527 
9528 
9529  }
9530 
9531 
9532  // pre-ratio idtsub
9533  idtsub=idtsub0;
9534 
9535 
9536 
9537  // dualfprintf(fail_file,"i=%d dtsub0=%g (realdt=%g)\n",ptrgeom->i,1/idtsub,realdt);
9538 
9539  // account for case where effect on fluid is more than on radiation (where above would only account for effect on radiation)
9540 
9541  // first compare to original U
9542  jj=TT; Umhd=UUMINLIMIT+fabs(U[UU+jj]);
9543  jj=TT; Urad=fabs(U[URAD0+jj]);
9544  idtsub=MAX(idtsub,idtsub0*Urad/Umhd);
9545 
9546  // dualfprintf(fail_file,"i=%d dtsub1=%g (realdt=%g)\n",ptrgeom->i,1/idtsub,realdt);
9547 
9548  // also compare against changed U=U0
9549  jj=TT; Umhd=UUMINLIMIT+fabs(U0[UU+jj]);
9550  jj=TT; Urad=fabs(U0[URAD0+jj]);
9551  idtsub=MAX(idtsub,idtsub0*Urad/Umhd);
9552 
9553  // dualfprintf(fail_file,"i=%d dtsub2=%g (realdt=%g) Urad=%g Umhd=%g\n",ptrgeom->i,1/idtsub,realdt,Urad,Umhd);
9554 
9555  }
9556  // below is if Diffusion is part of source term as in Koral
9557  // source term should lead to small (<1/2) change in conserved quantities
9558  else if(method==SPACETIMESUBSPLITNONE){
9559  // merged space-time to avoid negligible total momentum with large update needing to be resolved.
9560  Umhd=Urad=Gmhd=Grad=0.0;
9561  DLOOPA(jj) Umhd += fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9562  DLOOPA(jj) Urad += fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9563  DLOOPA(jj) Gmhd += fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9564  DLOOPA(jj) Grad += fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9565  iUmhd=1.0/(fabs(Umhd)+UUMINLIMIT);
9566  iUrad=1.0/(fabs(Urad)+UUMINLIMIT);
9567  idtsub=UUMINLIMIT+fabs(Gmhd*iUmhd);
9568  idtsub=MAX(idtsub,UUMINLIMIT+fabs(Grad*iUrad));
9569  idtsub=sqrt(idtsub);
9570 
9571  // if(1||realdt/(COURRADEXPLICIT/idtsub)>1.0) dualfprintf(fail_file,"UMHD: Umhdrad=%g %g : G=%g %g %g %g : Gmhdrad= %g %g :: iUmhdrad=%g %g ::: dtsub=%g realdt/dtsub=%g\n",Umhd,Urad,Gddtpl[UU],Gddtpl[U1],Gddtpl[U2],Gddtpl[U3],Gmhd,Grad,iUmhd,iUrad,COURRADEXPLICIT/idtsub,realdt/(COURRADEXPLICIT/idtsub));
9572 
9573  }
9574  else if(method==SPACETIMESUBSPLITTIME){
9575  // won't be efficient if v~0
9576  // if v<<1 and G is mid-range but still negligible, then dt will be incredibly small and code will halt if sub-cycling.
9577  Usmhd=Usrad=Gsmhd=Gsrad=0.0;
9578  Utmhd=Utrad=Gtmhd=Gtrad=0.0;
9579  SLOOPA(jj) Usmhd += fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9580  jj=TT; Utmhd += fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9581  SLOOPA(jj) Usrad += fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9582  jj=TT; Utrad += fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9583  SLOOPA(jj) Gsmhd += fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9584  jj=TT; Gtmhd += fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9585  SLOOPA(jj) Gsrad += fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9586  jj=TT; Gtrad += fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9587  iUsmhd=1.0/(fabs(Usmhd)+UUMINLIMIT);
9588  iUtmhd=1.0/(fabs(Utmhd)+UUMINLIMIT);
9589  iUsrad=1.0/(fabs(Usrad)+UUMINLIMIT);
9590  iUtrad=1.0/(fabs(Utrad)+UUMINLIMIT);
9591  idtsubs=SMALL+fabs(Gsmhd*iUsmhd);
9592  idtsubs=MAX(idtsubs,SMALL+fabs(Gsrad*iUsrad));
9593  idtsubt=SMALL+fabs(Gtmhd*iUtmhd);
9594  idtsubt=MAX(idtsubt,SMALL+fabs(Gtrad*iUtrad));
9595  idtsub=MAX(idtsubs,idtsubt);
9596  idtsub=sqrt(idtsub);
9597  }
9598  else if(method==SPACETIMESUBSPLITALL){
9599  // won't be efficient if flow becomes grid-aligned or if v~0
9600  Usmhd=Usrad=Gsmhd=Gsrad=0.0;
9601  idtsub=0.0;
9602  DLOOPA(jj){
9603  Umhd = fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9604  Urad = fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9605  Gmhd = fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9606  Grad = fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9607  iUmhd=1.0/(fabs(Umhd)+UUMINLIMIT);
9608  iUrad=1.0/(fabs(Urad)+UUMINLIMIT);
9609  idtsub=MAX(idtsub,SMALL+fabs(Gmhd*iUmhd));
9610  idtsub=MAX(idtsub,SMALL+fabs(Grad*iUrad));
9611  }
9612  }
9613  else if(method==SPACETIMESUBSPLITSUPERALL){
9614  // won't be efficient if flow becomes grid-aligned or if v~0 or if radiation neglibile contribution to fluid dynamics
9615  Usmhd=Usrad=Gsmhd=Gsrad=0.0;
9616  idtsub=0.0;
9617  DLOOPA(jj){
9618  Umhd = fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9619  Urad = fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9620  Gmhd = fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9621  Grad = fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9622  iUmhd=1.0/(fabs(Umhd)+UUMINLIMIT);
9623  iUrad=1.0/(fabs(Urad)+UUMINLIMIT);
9624  idtsub=MAX(idtsub,SMALL+fabs(Gmhd*iUmhd));
9625  idtsub=MAX(idtsub,SMALL+fabs(Grad*iUrad));
9626  }
9627  }
9628  else if(method==SPACETIMESUBSPLITMHDRAD){
9629  // merged space-time to avoid negligible total momentum with large update needing to be resolved.
9630  Umhd=Urad=Gmhd=Grad=0.0;
9631  idtsub=0.0;
9632  DLOOPA(jj) Umhd += fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9633  DLOOPA(jj) Urad += fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9634  DLOOPA(jj) Gmhd += fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9635  DLOOPA(jj) Grad += fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9636  iUmhd=1.0/(fabs(Umhd)+UUMINLIMIT);
9637  iUrad=1.0/(fabs(Urad)+UUMINLIMIT);
9638  idtsub=MAX(idtsub,SMALL+fabs(Gmhd*iUmhd));
9639  idtsub=MAX(idtsub,SMALL+fabs(Grad*iUrad));
9640 
9641  // dualfprintf(fail_file,"UMHD: %g %g %g %g %g %g\n",Umhd,Urad,Gtot,iUmhd,iUrad);
9642 
9643  }
9644  else if(method==SPACETIMESUBSPLITTIMEMHDRAD){
9645  // won't be efficient if v~0
9646  // if v<<1 and G is mid-range but still negligible, then dt will be incredibly small and code will halt.
9647  Usmhd=Usrad=Gsmhd=Gsrad=0.0;
9648  Utmhd=Utrad=Gtmhd=Gtrad=0.0;
9649  SLOOPA(jj) Usmhd += fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9650  jj=TT; Utmhd += fabs(U[UU+jj]*U[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9651  SLOOPA(jj) Usrad += fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9652  jj=TT; Utrad += fabs(U[URAD0+jj]*U[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9653  SLOOPA(jj) Gsmhd += fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9654  jj=TT; Gtmhd += fabs(Gddtpl[UU+jj]*Gddtpl[UU+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9655  SLOOPA(jj) Gsrad += fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9656  jj=TT; Gtrad += fabs(Gddtpl[URAD0+jj]*Gddtpl[URAD0+jj]*ptrgeom->gcon[GIND(jj,jj)]);
9657  iUsmhd=1.0/(fabs(Usmhd)+UUMINLIMIT);
9658  iUtmhd=1.0/(fabs(Utmhd)+UUMINLIMIT);
9659  iUsrad=1.0/(fabs(Usrad)+UUMINLIMIT);
9660  iUtrad=1.0/(fabs(Utrad)+UUMINLIMIT);
9661  idtsub=SMALL;
9662  idtsub=MAX(idtsub,SMALL+fabs(Gsmhd*iUsmhd));
9663  idtsub=MAX(idtsub,SMALL+fabs(Gsrad*iUsrad));
9664  idtsub=MAX(idtsub,SMALL+fabs(Gtmhd*iUtmhd));
9665  idtsub=MAX(idtsub,SMALL+fabs(Gtrad*iUtrad));
9666  }
9667 
9668 
9669 
9670  // what to return
9671  *dtsub=COURRADEXPLICIT/idtsub;
9672 
9673 
9674 
9675  // dualfprintf(fail_file,"*dtsub=%g idtsub=%g method=%d\n",*dtsub,idtsub,method);
9676 
9677 }
9678 
9679 #define EXPLICITFAILEDBUTWENTTHROUGH -2
9680 #define EXPLICITNOTNECESSARY -1
9681 #define EXPLICITNOTFAILED 0 // should stay zero
9682 #define EXPLICITFAILED 1 // should stay one
9683 
9684 
9685 #define GETADVANCEDUNEW0FOREXPLICIT 1 // Use this to check if single explicit step was really allowable, but get_dtsub() already uses advanced U. But chi will be not updated for fluid dUriemann update, so still might want to do this (with proper code changes) in order to get chi good.
9686 
9694 static int source_explicit(int whichsc, int whichradsourcemethod, int methoddtsub,int *eomtype,
9695  void (*sourcefunc)(int methoddtsub, FTYPE *pr, FTYPE *Ui, FTYPE *Uf, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gpl, struct of_geom *ptrgeom, FTYPE *dtsub),
9696  FTYPE *pb, FTYPE *piin, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE *dUother, FTYPE (*dUcomp)[NPR])
9697 {
9698  int pliter, pl;
9699 
9700  int eomtypelocal=*eomtype; // default
9701 
9703  //
9704  // SETUP LOOPS
9705  //
9707  int showmessages=0;
9708  int showmessagesheavy=0;
9709  int allowlocalfailurefixandnoreport=0; // need to see if any failures.
9710  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
9711  // initialize counters
9712  newtonstats.nstroke=newtonstats.lntries=0;
9713  int finalstep = 0; //can choose either 1 or 0 depending on whether want floor-like fixups (1) or not (0). unclear which one would work best since for Newton method to converge might want to allow negative density on the way to the correct solution, on the other hand want to prevent runaway into rho < 0 region and so want floors.
9714 
9715 
9716  // if(1||nstep>=800){
9717  // showmessages=showmessagesheavy=1;
9718  // }
9719 
9721  //
9722  // SETUP U and P and q
9723  //
9725 
9726  FTYPE pb0[NPR],Uiin0[NPR];
9727  FTYPE prnew[NPR],Unew[NPR],Unew0[NPR];
9728  FTYPE prforG[NPR];
9729  struct of_state q0,qnew;
9730  FTYPE Gpl[NPR];
9731  FTYPE chi;
9732 
9733  // backup pb, Uiin, and q and setup "new" versions to be iterated
9734  PLOOP(pliter,pl) prnew[pl]=pb0[pl]=pb[pl];
9735  PLOOP(pliter,pl) Unew[pl]=Uiin0[pl]=Uiin[pl];
9736  qnew=q0=*q;
9737 
9738 
9739  // get updated U (try getting full update)
9740  FTYPE fracdtuu0=1.0; // try full uu0 at first
9741  FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
9742  PLOOP(pliter,pl) Unew[pl]=Unew0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall);
9743 
9744  // if reversion from implicit, then no choice but to push through CASE radiation errors and hope the reductions there are ok. Would be worse to have no reversion solution!
9745  int pushthroughraderror=0;
9746  if(whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT){
9747  pushthroughraderror=1;
9748  }
9749 
9750 
9751 
9752  // Get prnew(Unew) using largest fracdtuu0 possible in order to get realistic estimate of dtsub
9753  // used to use this as starting point for U, but that wasn't consistent with explicit stepping
9756  //
9757  // Get good Unew0 that has P(Unew0) solution
9758  //
9760  while(1){ // loop bounded by fracdtuu0 becoming too small
9761  // Get pnew from Unew
9762  // OPTMARK: Should optimize this to not try to get down to machine precision
9763  // initialize counters
9764  newtonstats.nstroke=newtonstats.lntries=0;
9765  int doradonly=0;
9766  int whichcap=CAPTYPEBASIC;
9767  eomtypelocal=*eomtype; // re-default
9768  int radinvmod=0;
9769  FTYPE dissmeasure=-1.0; // assume ok to try energy
9770  int checkoninversiongas;
9771  int checkoninversionrad;
9772  // don't check since slows down code and could be good enough solution if original error says ok.
9773  checkoninversiongas=checkoninversionrad=0;
9774  //
9775  int failutoprim=Utoprimgen_failwrapper(doradonly,&radinvmod,showmessages,checkoninversiongas,checkoninversionrad, allowlocalfailurefixandnoreport, finalstep, &eomtypelocal, whichcap, EVOLVEUTOPRIM, UNOTHING, Unew, q, ptrgeom, dissmeasure, prnew, &newtonstats);
9776 
9777  if(failutoprim){
9778 
9779  if(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLE || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT){
9780  // then ok to be here
9781  }
9782  else{
9783  // if here, then must be doing implicit checks, so return that should just do implicit instead of any more expensive calculations here.
9784  return(EXPLICITFAILED);
9785  }
9786 
9787  // backing off dU
9788  fracdtuu0*=0.5;
9789 
9790  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"Backing off fracdtuu0=%g\n",fracdtuu0);
9791 
9792  if(fracdtuu0<NUMEPSILON){
9793  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"In explicit, backed-off to very small level of fracdtuu0=%g, so must abort\n",fracdtuu0);
9794  if(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLE || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT){
9795  // just use initial Unew0 then
9796  fracdtuu0=0.0;
9797  break;
9798  }
9799  else return(EXPLICITFAILED);
9800  }
9801  else{
9802  // recompute use of full dU so Unew0 is updated
9803  // FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
9804  PLOOP(pliter,pl) Unew[pl]=Unew0[pl]=UFSET(CUf,fracdtuu0*dt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall);
9805  // reset prnew
9806  PLOOP(pliter,pl) prnew[pl]=pb0[pl]=pb[pl];
9807  }
9808 
9809  }
9810  else{
9811  // then found good Unew0
9812  break;
9813  }
9814  }// end while trying to get good Unew0
9815 
9816  }
9817 
9819  //
9820  // Get future force and dtsub so don't overestimate dtsub for first sub-cycle steps and end-up possibly jumping too far
9821  //
9823  // get prforG to compute G and chi for calc_dtsub() to ensure future update doesn't have radically different opacity and so 4-force and underpredict that implicit or sub-cycles are needed.
9824  PLOOP(pliter,pl) prforG[pl]=prnew[pl];
9825 
9826 
9827  // get dtsubforG (don't use Gpl from this)
9828  FTYPE dtsubforG;
9829  sourcefunc(methoddtsub, prforG, Uiin, Ufin, dUother, CUf, CUimp, Gpl, ptrgeom, &dtsubforG);
9830  // dualfprintf(fail_file,"dtsubforG=%g\n",dtsubforG);
9831 
9832  if(!(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT)){
9833  // then if sub-cycling, really want to start with beginning pb so consistently do sub-steps for effective flux force and full-pl fluid force in time.
9834  // But if end-up doing just one explcit step, then probably wanted to use time-advanced prnew as estimate. That gives more stable result.
9835  // then prforG is only used to ensure not getting bad guess for whether *should* sub-cycle.
9836  PLOOP(pliter,pl) prnew[pl]=pb[pl];
9837  }
9838 
9839 
9841  //
9842  // SETUP explicit sub-cycle LOOP
9843  //
9845  FTYPE dttrue=0.0,dtcum=0.0; // cumulative sub-cycle time
9846  FTYPE dtdiff;
9847  FTYPE dtsub,dtsubold,dtsubuse;
9848  int isexplicit=1;
9849  FTYPE realdt=compute_dt(isexplicit,CUf, CUimp,dt);
9850  FTYPE fracdtG;
9851 
9852  int jj;
9853  FTYPE Gplprevious[NPR]={0}, sourcepl[NPR];
9854 
9855 
9856  // initialize source update
9857  PLOOP(pliter,pl) sourcepl[pl] = 0;
9858 
9860  //
9861  // explicit source LOOP
9862  //
9864  int itersub=0;
9865  int done=0;
9866  while(1){
9867 
9868 
9869  // get 4-force for full pl set
9870  PLOOP(pliter,pl) Gplprevious[pl]=Gpl[pl];
9871  // get Gpl and dtsub for sub-cycling
9872  sourcefunc(methoddtsub, prnew, Uiin, Ufin, dUother, CUf, CUimp, Gpl, ptrgeom, &dtsub);
9873  if(itersub==0) PLOOP(pliter,pl) Gplprevious[pl]=Gpl[pl]; // constant interpolation rather than just using zero for midpoint method
9874  if(itersub==0 && dtsub>dtsubforG) dtsub=dtsubforG; // ensure initial sub-stepping is not too large due to large state changes not accounted for yet. Assuming slow safety factor growth in dtsub can occur from then on and that's ok since will catch updated state change to some fraction.
9875  // dualfprintf(fail_file,"itersub=%d dtsub=%g\n",itersub,dtsub);
9876 
9877 
9878  // if no solution for implicit and come to explicit, then failure can manifest as T large and then Gpl->nan or inf. Must fail this scenario.
9879  // This can happen even when have gotten quite close to end of step, but just no actually solution for the accurate value of U0 and G
9880  PLOOP(pliter,pl) if(!isfinite(Gpl[pl])) return(EXPLICITFAILED);
9881 
9882 
9883  if(showmessagesheavy&&debugfail>=2){
9884  PLOOP(pliter,pl) dualfprintf(fail_file,"SOURCE: pl=%d Gpl=%g dtsub=%g realdt=%g prnew=%g Uiin=%g Ufin=%g dUother=%g\n",pl,Gpl[pl],dtsub,realdt,prnew[pl],Uiin[pl],Ufin[pl],dUother[pl]);
9885  }
9886 
9887  if(whichradsourcemethod==SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLECHECKSFROMIMPLICIT){
9888  // then just check if need sub-cycles, and exit if so
9889  if(realdt>dtsub) return(EXPLICITFAILED);
9890  // else can do explicit step (or sub-cycles if happen to switch to them) and can avoid implicit step
9891  }
9892  // if still here, then even with implicit checks, doing either explicit or sub-cycle explicit stepping
9893 
9895  // get fracdtG
9897 
9898  if(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT){
9899  fracdtG=1.0;
9900  }
9901  else{
9902 
9903  if(realdt/dtsub>MAXSUBCYCLESFAIL){
9904  // then some major issue
9905  if(debugfail>=2) dualfprintf(fail_file,"MAJOR explicit issue: realdt=%g dtsub=%g and aborted assuming no real solution and that best approximation is no force.\n");
9906  return(EXPLICITFAILED);
9907  }
9908  else if(realdt/dtsub>MAXSUBCYCLES && whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT){
9909  // Use MAXSUBCYCLES if otherwise was trying implicit.
9910  // Impractical to assume if really revert to explicit (or really trying to use it) then rarely occurs or want to solve for actual solution, so do all needed sub-cycles!
9911  // Semi-required to limit number of cycles for non-simple "methoddtsub" procedure that can produce arbitrarily small dtsub due to (e.g.) momentum term or something like that.
9912  // NOTE: For high \tau, rad velocity entering chars goes like 1/\tau, so that timestep is higher. But dtsub remains what it should be for explicit stepping, and so in high-tau case, explicit steps required per actual step goes like \tau^2. So "kinda" ok that takes long time for explicit sub-stepping since ultimately reaching longer time.
9913  if(showmessages && debugfail>=2) dualfprintf(fail_file,"itersub=%d dtsub very small: %g with realdt=%g and only allowing MAXSUBCYCLES=%d subcycles, so limit dtsub: ijk=%d %d %d\n",itersub,dtsub,realdt,MAXSUBCYCLES,ptrgeom->i,ptrgeom->j,ptrgeom->k);
9914  dtsub=realdt/(FTYPE)MAXSUBCYCLES;
9915  }
9916  else if(NUMEPSILON*dtsub>=realdt && itersub==0){
9917  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"explicit not necessary\n");
9918  // then no need for source term at all
9919  return(EXPLICITNOTNECESSARY);
9920  }
9921 
9922 
9923  if(itersub==0) dtsubold=dtsubuse=dtsub;
9924  else{
9925  // override if dtsub is larger than realdt, indicating really done with iterations and reached some equilibrium, so no longer necessary to check vs. dtsubold
9926  // No, too speculative.
9927  // if(dtsub>realdt) dtsub=realdt;
9928 
9929  // ensure don't change step too fast. Sometimes first guess for dtsub can be small, and very next iteration suggests very large. Not trustable, so stay slow.
9930  if(dtsub>dtsubold*(1.0+MAXEXPLICITSUBSTEPCHANGE)) dtsubuse=dtsubold*(1.0+MAXEXPLICITSUBSTEPCHANGE);
9931  else dtsubuse=dtsub;
9932 
9933  // need to compare with previous actual dt
9934  dtsubold=dtsubuse;
9935  }
9936 
9937  // time left to go in sub-cycling
9938  dtdiff=MAX(realdt-dtcum,0.0);
9939  dttrue=MIN(dtsubuse,dtdiff);
9940  fracdtG=MIN(1.0,dttrue/realdt); // expect fraction of G that can be handled is similar to what sub-cycle requires for stable explicit stepping
9941 
9942 
9943  if(showmessagesheavy&&debugfail>=2){
9944  dualfprintf(fail_file,"DoingSUBCYCLE: itersub=%d : dtsub=%g dtsubuse=%g dtdiff=%g dttrue=%g dtcum=%g realdt=%g fracdtG=%g ijk=%d %d %d\n",itersub,dtsub,dtsubuse,dtdiff,dttrue,dtcum,realdt,fracdtG,ptrgeom->i,ptrgeom->j,ptrgeom->k);
9945  }
9946  if(debugfail>=2 && (1||showmessages)&&(1.0/fracdtG>MAXSUBCYCLES && itersub==0)){ // have to use itersub==0 since already might be done with itersub==1 and then fracdtG=inf (but itersub=0 might be using bad force)
9947  dualfprintf(fail_file,"DoingLOTSofsub-cycles: ijk=%d %d %d 1/fracdtG=%g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,1.0/fracdtG);
9948  }
9949  }// end else if not explicit
9950 
9951 
9952 
9953  // add to final result if starting point is full U0
9954  // forward step integration
9955  // PLOOP(pliter,pl) sourcepl[pl] += Gpl[pl]*fracdtG;
9956  // Trapezoidal Rule (midpoint method):
9957  PLOOP(pliter,pl) sourcepl[pl] += 0.5*(Gplprevious[pl]+Gpl[pl])*fracdtG;
9958 
9959 
9960 
9962  //
9963  // see if done
9964  //
9966  if(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT){
9967  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"explicit done\n");
9968  break;
9969  }
9970  else if(whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLE || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLECHECKSFROMIMPLICIT){
9971  if(dtcum>=realdt){
9972  // then done
9973  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"explicit sub-cycle done\n");
9974  break;
9975  }
9976  else{
9977  // then keep sub-cycling _or_ getting balance of U and G
9978  }
9979  }
9980  else{
9981  if(fracdtG!=1.0){
9982  // if here, then must be doing implicit checks, so return that should just do implicit instead of sub-cycling.
9983  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"explicit sub-cycle can't be done.\n");
9984  return(EXPLICITFAILED);
9985  }
9986  else{
9987  // then implicit testing, and had to do step, but only 1 step, so consider success.
9988  // still need to fill dUcomp[] below
9989  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"explicit success, just one step.\n");
9990  break;
9991  }
9992  }
9993 
9995  // If not done, get prnew from Unew for next step
9997 
9998  // get new Unew0
9999  FTYPE xint=(dtcum/realdt);
10000  // NOTE: Below interpolates from Unew0 could use up to final, but not consistent with explicit stepping and leads to erroneous 0-force results.
10001  // FTYPE fakefracdtuu0=fracdtuu0*(1.0-xint) + 1.0*(xint);
10002  // NOTE: Below interpolates from step's true starting Unew0 to step's final Unew0 assuming linear interpolation between -- *most* consistent with explicit stepping!!
10003  FTYPE fakefracdtuu0=1.0*(xint);
10004  // NOTE: Below sticks to the Unew0 that could use, but not consistent with explicit stepping and leads to erroneous 0-force results.
10005  // FTYPE fakefracdtuu0=fracdtuu0;
10006  FTYPE tempdt= fakefracdtuu0*dt; // uses dt here, because below UFSET() computes "realdt" using CUf internally
10007  // FTYPE dUnongeomall[MAXTIMEORDER]={0.0};
10008  PLOOP(pliter,pl) Unew0[pl]=UFSET(CUf,tempdt,Uiin[pl],Ufin[pl],dUother[pl],0.0,dUnongeomall);
10009 
10010 
10011  // get new Unew using 1) current Unew0 (so Unew updates a bit towards final Unew0 as if fracdtuu0=1) and 2) cumulative 4-force so far
10012  PLOOP(pliter,pl) Unew[pl] = Unew0[pl] + sourcepl[pl] * realdt;
10013 
10014  // get prnew(Unew)
10015  newtonstats.nstroke=newtonstats.lntries=0;
10016  int doradonly=0;
10017  eomtypelocal=*eomtype; // re-default
10018  int whichcap=CAPTYPEBASIC;
10019  int radinvmod=0;
10020  FTYPE dissmeasure=-1.0; // assume ok to try energy
10021  int checkoninversiongas=CHECKONINVERSION;
10022  int checkoninversionrad=CHECKONINVERSIONRAD;
10023  int failutoprim=Utoprimgen_failwrapper(doradonly,&radinvmod,showmessages,checkoninversiongas,checkoninversionrad, allowlocalfailurefixandnoreport, finalstep, &eomtypelocal, whichcap, EVOLVEUTOPRIM, UNOTHING, Unew, q, ptrgeom, dissmeasure, prnew, &newtonstats);
10024  // push through inversion failure if just radiation inversion failure since have local fixups that can be ok or even recovered from. Bad to just stop if doing reversion from implicit.
10025  if(pushthroughraderror==0 && failutoprim==UTOPRIMGENWRAPPERRETURNFAILRAD || pushthroughraderror==1 && failutoprim==UTOPRIMGENWRAPPERRETURNFAILMHD){
10026  if(showmessages && debugfail>=2) dualfprintf(fail_file,"BAD: Utoprimgen_wrapper() failed during explicit sub-stepping. So sub-cycling failed.\n");
10027  return(EXPLICITFAILED);
10028  }
10029 
10030 
10031  // DEBUG:
10032  if(showmessagesheavy &&debugfail>=2) PLOOP(pliter,pl) dualfprintf(fail_file,"POSTEXSTEP: pl=%2d Unew0=%21.15g Unew=%21.15g sourcepl*realdt=%21.15g fakefracdtuu0=%g\n",pl,Unew0[pl],Unew[pl],sourcepl[pl]*realdt,fakefracdtuu0);
10033 
10034 
10035  // step
10036  dtcum += realdt*fracdtG; // cumulative true time
10037  itersub++;
10038 
10039 
10040  }// done looping
10041 
10042 
10044  //
10045  // apply 4-force as update in dUcomp[][]
10046  // only changed this quantity, none of other among function arguments
10047  //
10049  PLOOP(pliter,pl) dUcomp[whichsc][pl] += sourcepl[pl];
10050 
10051  // save better guess for later inversion from this inversion
10052  PLOOP(pliter,pl) pb[pl]=prnew[pl];
10053 
10054  // save eomtype settled on
10055  *eomtype=eomtypelocal;
10056 
10057 
10058  return(EXPLICITNOTFAILED);
10059 
10060 }
10061 
10062 
10063 
10064 
10065 
10066 
10067 
10068 
10073 int koral_source_rad(int whichradsourcemethod, FTYPE *piin, FTYPE *pb, FTYPE *pf, int *didreturnpf, int *eomtype, FTYPE *Uiin, FTYPE *Ufin, FTYPE *CUf, FTYPE *CUimp, struct of_geom *ptrgeom, struct of_state *q, FTYPE dissmeasure, FTYPE *dUother, FTYPE (*dUcomp)[NPR])
10074 {
10075  int pliter,pl;
10076  int showmessages=0; // 0 ok if not debugging and think everything works.
10077  int showmessagesheavy=0;
10078 
10079  // if(1||nstep>=800){
10080  // showmessages=showmessagesheavy=1;
10081  // }
10082 
10083 
10084  // make code use "orig" values that below can modify, so return preserves no changes to these no matter what internal functions do.
10085  // save pb, Uiin, Ufin, and q to avoid being modified upon return
10086  FTYPE pborig[NPR],pforig[NPR],piinorig[NPR],Uiinorig[NPR],Ufinorig[NPR];
10087  struct of_state qorigmem;
10088  struct of_state *qorig=&qorigmem;
10089  PLOOP(pliter,pl){
10090  pborig[pl]=pb[pl];
10091  pforig[pl]=pf[pl];
10092  piinorig[pl]=piin[pl];
10093  Uiinorig[pl]=Uiin[pl];
10094  Ufinorig[pl]=Ufin[pl];
10095  }
10096  *qorig=*q;
10097 
10098 
10100  //
10101  // Check energy density to see if even any radiation or will be any radiation
10102  // Note, can't just check size of Erf, because in non-LTE, B can be large even if E is not.
10103  //
10105 
10106 
10107 
10109  //
10110  // EXPLICIT TYPES
10111  //
10113  if(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLE || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLECHECKSFROMIMPLICIT){
10114 
10115 
10116  if(TIMETYPE==TIMEIMPLICIT){
10117  dualfprintf(fail_file,"Makes no sense to do explicit source (with or without subcycling) and IMEX stepping\n");
10118  myexit(937453984);
10119  }
10120 
10121 
10122 
10123  int methoddtsub;
10124  // SPACETIMESUBSPLITMHDRAD doesn't work -- generates tons of noise in prad1 with COURRADEXPLICIT=0.2, and was asymmetric in x.
10125  methoddtsub=TAUSUPPRESS; // forced -- only method that is efficient and effective and noise free at moderate optical depths.
10126  // methoddtsub=SPACETIMESUBSPLITNONE;
10127  // methoddtsub=SPACETIMESUBSPLITTIME;
10128 
10129 
10130  int whichsc = RADSOURCE;
10131  // try explicit (with or without sub-cycling)
10132  // dualfprintf(fail_file,"Trying explicit: whichradsourcemethod=%d\n",whichradsourcemethod);
10133  int failexplicit=source_explicit(whichsc, whichradsourcemethod,methoddtsub,eomtype,koral_source_dtsub_rad_calc,pborig, piinorig, Uiinorig, Ufinorig, CUf, CUimp, ptrgeom, qorig, dUother, dUcomp);
10134  if(failexplicit==EXPLICITFAILED){
10135  if(whichradsourcemethod==SOURCEMETHODEXPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLE || whichradsourcemethod==SOURCEMETHODEXPLICITREVERSIONFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT){
10136  // still do explicit anyways, since best can do with the choice of method -- will fail possibly to work if stiff regime, but ok in non-stiff.
10137  // assume nothing else to do, BUT DEFINITELY report this.
10138  if(debugfail>=2) dualfprintf(fail_file,"BAD: explicit failed: ijk=%d %d %d : whichradsourcemethod=%d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,whichradsourcemethod);
10139  *didreturnpf=0;
10140  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILCASE3A; // must set as failure in case can fixup.
10142  }
10143  else if(whichradsourcemethod==SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLECHECKSFROMIMPLICIT){
10144  // tells that explicit didn't work for implicit checks
10145  if(showmessages && debugfail>=2) dualfprintf(fail_file,"explicit failed for implicit check. ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10146  *didreturnpf=0;
10147  return(EXPLICITFAILED);
10148  }
10149  else{
10150  // tells that explicit didn't work
10151  if(showmessages && debugfail>=2) dualfprintf(fail_file,"explicit failed. ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10152  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILCASE3B; // must set as failure in case can fixup.
10153  *didreturnpf=0;
10154  return(EXPLICITFAILED);
10155  }
10156  }
10157  else if(failexplicit==EXPLICITNOTNECESSARY){
10158  // then don't need any source term
10159  if(debugfail>=2) dualfprintf(fail_file,"ODD: explicit found not necessary while implicit failed: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10160  *didreturnpf=0;
10161  return(0);
10162  }
10163 
10164  //else explicit succeeded, so just return
10165  if(whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLE || whichradsourcemethod==SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT){
10166  // if sub-cycled, then have better pf than pb assumed saved in pborig[].
10167  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"explicit didn't fail. ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10168  PLOOP(pliter,pl) pf[pl]=pborig[pl];
10169  *didreturnpf=1;
10170  }
10171  return(EXPLICITNOTFAILED);
10172  }
10174  //
10175  // IMPLICIT TYPES (implicit function should handle pflag (rad or gas) error issues), but still leave explicit as handling error mode here
10176  //
10178  else if(whichradsourcemethod==SOURCEMETHODIMPLICIT){
10179 
10180 
10181  // If doing implicit, first check if using TIMEIMPLICIT. If so, then check if CUf CUnew implies no contribution to compute. If so, return without computation
10182  if(TIMETYPE==TIMEIMPLICIT){
10183  int doradimplicit = (CUimp[0]!=0.0); // || CUnewimp[0]!=0.0); // assuming M^i only created and added if added to Uf and U^{n+1} at same step.
10184  if(doradimplicit){
10185  // then continue and do implicit solution and compute_dt() will use CUimp[]
10186  }
10187  else{
10188  // then return as if successful, but don't assume inversion already done for pf (since not)
10189  // NOTE: We don't return explicit version of answer either -- just simply zero. Since dUcomp already set as zero when initialized, nothing to do. (as if never was doing source term)
10190  PLOOP(pliter,pl) pf[pl]=pborig[pl];
10191  *didreturnpf=0;
10192  return(0);
10193  }
10194  // then do implicit step
10195  }
10196  else{
10197  // else just follow flux behavior
10198  }
10199 
10200 
10201  int failimplicit=koral_source_rad_implicit(eomtype, pborig, pforig, piinorig, Uiinorig, Ufinorig, CUf, CUimp, ptrgeom, qorig, dissmeasure, dUother, dUcomp);
10202 
10203  if(failimplicit>0){
10204  if(IMPLICITREVERTEXPLICIT){ // single level recusive call (to avoid duplicate confusing code)
10205  // assume if revert from implicit, then need to do sub-cycles
10206  int failexplicit=koral_source_rad(SOURCEMETHODEXPLICITSUBCYCLEREVERSIONFROMIMPLICIT, piinorig, pborig, pf, didreturnpf, eomtype, Uiinorig, Ufinorig, CUf, CUimp, ptrgeom, qorig, dissmeasure, dUother, dUcomp);
10207  if(failexplicit==EXPLICITFAILED){
10208  // nothing else to revert to, but just continue and report
10209  *didreturnpf=0;
10210  if(debugfail>=2) dualfprintf(fail_file,"BAD: explicit failed while implicit failed: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10211  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILCASE1A; // must set as failure in case can fixup.
10212  return(0);
10213  }
10214  else if(failexplicit==EXPLICITNOTNECESSARY){
10215  // then don't need any source term
10216  if(debugfail>=2) dualfprintf(fail_file,"ODD: explicit found not necessary while implicit failed: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10217  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILCASE1B; // must set as failure in case can fixup.
10218  *didreturnpf=0;
10219  return(0);
10220  }
10221  else if(failexplicit==EXPLICITFAILEDBUTWENTTHROUGH){
10222  // then had issues, but nothing else can do.
10223  if(debugfail>=2) dualfprintf(fail_file,"HMM: explicit found necessary and had problems while implicit failed: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10224  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILCASE2A; // must set as failure in case can fixup.
10225  *didreturnpf=0;
10226  return(0);
10227  }
10228  else{
10229  // if sub-cycled, then have better pf than pb assumed saved in pborig[].
10230  if(debugfail>=2) dualfprintf(fail_file,"GOOD: explicit worked while implicit failed (%d): ijk=%d %d %d\n",failexplicit,ptrgeom->i,ptrgeom->j,ptrgeom->k);
10231  PLOOP(pliter,pl) pf[pl]=pborig[pl];
10232  *didreturnpf=1;
10233  return(0);
10234  }
10235  }// end if reverting to explicit
10236  else{
10237  *didreturnpf=0;
10238  if(debugfail>=2) dualfprintf(fail_file,"BAD: implicit failed and didn't choose to revert: ijknstepsteppart=%d %d %d %ld %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart);
10239  // GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADFAILCASE2B; // must set as failure in case can fixup. // NO, leave implicit call as handling error mode.
10240  return(0);
10241  }
10242  }// end if failed to do implicit
10243  else if(failimplicit==0){
10244  // no failure in implicit, then just return
10245  // and if did implicit, then better pf guess for any future inversions
10246  PLOOP(pliter,pl) pf[pl]=pborig[pl];
10247  *didreturnpf=1;
10248  }
10249  else{
10250  *didreturnpf=0;
10251  // e.g. if failimplicit==FAILRETURNGOTRIVIALEXPLICIT, then aborted implicit and letting trivial explicit operate.
10252  }
10253  // if(debugfail>=2) dualfprintf(fail_file,"Good: Imlicit good.: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10254  return(0);
10255 
10256  }
10258  //
10259  // IMPLICIT WITH EXPLICIT CHECK TYPES
10260  //
10262  else if(whichradsourcemethod==SOURCEMETHODIMPLICITEXPLICITCHECK){
10263 
10264  // try explicit (or see if no source at all required)
10265  // Just check using explicit method, since if sub-cycles required then should just do implicit
10266  int failreturn=koral_source_rad(SOURCEMETHODEXPLICITCHECKSFROMIMPLICIT, piinorig, pborig, pf, didreturnpf, eomtype, Uiinorig, Ufinorig, CUf, CUimp, ptrgeom, qorig, dissmeasure, dUother, dUcomp);
10267 
10268  // determine if still need to do implicit
10269  // don't set didreturnpf since already was set
10270  int doimplicit;
10271  if(failreturn==EXPLICITFAILED || failreturn==EXPLICITFAILEDBUTWENTTHROUGH || GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)>UTOPRIMRADNOFAIL){
10272  doimplicit=1;
10273  GLOBALMACP0A1(pflag,ptrgeom->i,ptrgeom->j,ptrgeom->k,FLAGUTOPRIMRADFAIL)=UTOPRIMRADNOFAIL; // reset and let implicit set this
10274  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"NOTE: Tried explicit step, but wasn't good choice or failed: ijk=%d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10275  // don't return until do implicit
10276  }
10277  else if(failreturn==EXPLICITNOTNECESSARY){
10278  // then no source at all required
10279  doimplicit=0;
10280  return(0);
10281  }
10282  else{
10283  doimplicit=0;
10284  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"NOTE: Was able to take explicit step: ijk=%d %d %d : failreturn=%d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,failreturn);
10285  return(0);
10286  }
10287 
10288 
10289  if(doimplicit){
10290  if(showmessagesheavy && debugfail>=2) dualfprintf(fail_file,"NOTE: Had to take implicit step: %d %d %d\n",ptrgeom->i,ptrgeom->j,ptrgeom->k);
10291 
10292  // one-deep recursive call to implicit scheme
10293  return(koral_source_rad(SOURCEMETHODIMPLICIT, piinorig, pborig, pf, didreturnpf, eomtype, Uiinorig, Ufinorig, CUf, CUimp, ptrgeom, qorig, dissmeasure, dUother, dUcomp));
10294  }// end if doimplicit==1
10295 
10296  }
10298  //
10299  // NO SOURCE TYPE
10300  //
10302  else if(whichradsourcemethod==SOURCEMETHODNONE){
10303  // then no source applied even if required
10304  *didreturnpf=0;
10305  return(0);
10306  }
10308  //
10309  // UNKNOWN TYPE
10310  //
10312  else{
10313 
10314  dualfprintf(fail_file,"3 No Such EOMRADTYPE=%d\n",EOMRADTYPE);
10315  myexit(18754363);
10316 
10317  }
10318 
10319  // KORALTODO: SUPERGODMARK: Need to add NR 2007 page940 17.5.2L StepperSie method here as higher-order alternative if 1st order Newton breaks
10320 
10321 
10322  return(0);
10323 
10324 }
10325 
10326 
10327 
10328 
10329 
10330 
10331 
10332 
10333 
10334 
10335 
10340 // just for chi and tautot
10341 void calc_kappa(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *kappa)
10342 {
10343  extern FTYPE calc_kappa_user(FTYPE rho, FTYPE B, FTYPE Tg,FTYPE Tr,FTYPE expfactorrad, FTYPE x,FTYPE y,FTYPE z);
10344  //user_calc_kappa()
10345  FTYPE rho=pr[RHO];
10346  FTYPE u=pr[UU];
10347  int ii=ptrgeom->i;
10348  int jj=ptrgeom->j;
10349  int kk=ptrgeom->k;
10350  int loc=ptrgeom->p;
10351  FTYPE Tgas=compute_temp_simple(ii,jj,kk,loc,rho,u);
10352 
10353  FTYPE Tradff,nradff,expfactorradff;
10354  FTYPE bsq,B;
10355  if(q==NULL){
10356  // Trad=Tgas; // estimate for opacity (worse than below)
10357  FTYPE Ruufake=pr[PRAD0]; // estimate for opacity
10358  Tradff = pow(fabs(Ruufake)/ARAD_CODE,0.25); // ASSUMPTION: PLANCK
10359  expfactorradff=1.0; // Planck
10360  //nradff not used here, so don't have to set
10361  bsq_calc(pr,ptrgeom,&bsq);
10362  }
10363  else{
10364  calc_Trad(pr,ptrgeom,q,&Tradff,&nradff,&expfactorradff); // kinda expensive, avoid if not really necessary (could set Trad=Tgas, just for opacity purposes)
10365  bsq = dot(q->bcon, q->bcov);
10366  }
10367  B=sqrt(bsq);
10368 
10369  FTYPE V[NDIM]={0.0},xx=0.0,yy=0.0,zz=0.0;
10370 #if(ALLOWKAPPAEXPLICITPOSDEPENDENCE)
10371  bl_coord_ijk(ii,jj,kk,loc,V);
10372  xx=V[1];
10373  yy=V[2];
10374  zz=V[3];
10375 #endif
10376  *kappa = calc_kappa_user(rho,B,Tgas,Tradff,expfactorradff,xx,yy,zz);
10377  // dualfprintf(fail_file,"kappaabs=%g\n",*kappa);
10378 
10379  if(AVOIDTAUFORFLOOR==1){
10380  FTYPE bsqorholimit=10.0; //BSQORHOLIMIT/5.0;
10381  FTYPE factor;
10382  FTYPE thebsqorho=bsq/rho;
10383  if(bsq/rho<0 || bsq/rho>BSQORHOLIMIT) thebsqorho=BSQORHOLIMIT;
10384  factor=exp(-thebsqorho/bsqorholimit);
10385  *kappa *= factor;
10386  }
10387 
10388 
10389 }
10390 
10391 
10393 // just for chi and tautot
10394 void calc_kappaes(FTYPE *pr, struct of_geom *ptrgeom, FTYPE *kappaes)
10395 {
10396  extern FTYPE calc_kappaes_user(FTYPE rho, FTYPE T,FTYPE x,FTYPE y,FTYPE z);
10397  //user_calc_kappaes()
10398  FTYPE rho=pr[RHO];
10399  FTYPE u=pr[UU];
10400  int ii=ptrgeom->i;
10401  int jj=ptrgeom->j;
10402  int kk=ptrgeom->k;
10403  int loc=ptrgeom->p;
10404  FTYPE T=compute_temp_simple(ii,jj,kk,loc,rho,u);
10405  FTYPE V[NDIM]={0.0},xx=0.0,yy=0.0,zz=0.0;
10406 #if(ALLOWKAPPAEXPLICITPOSDEPENDENCE)
10407  bl_coord_ijk(ii,jj,kk,loc,V);
10408  xx=V[1];
10409  yy=V[2];
10410  zz=V[3];
10411 #endif
10412  *kappaes = calc_kappaes_user(rho,T,xx,yy,zz);
10413  // dualfprintf(fail_file,"kappaes=%g\n",*kappa);
10414 
10415  if(AVOIDTAUFORFLOOR==1){
10416  FTYPE bsq;
10417  bsq_calc(pr, ptrgeom, &bsq);
10418  FTYPE bsqorholimit=10.0; //BSQORHOLIMIT/5.0;
10419  FTYPE factor;
10420  FTYPE thebsqorho=bsq/rho;
10421  if(bsq/rho<0 || bsq/rho>BSQORHOLIMIT) thebsqorho=BSQORHOLIMIT;
10422  factor=exp(-thebsqorho/bsqorholimit);
10423  *kappaes *= factor;
10424  }
10425 
10426 }
10427 
10428 
10429 // compute \chi TODOMARK: Should compute this and wavespeed (how this used) just after implicit stepping to avoid repeating opacity calculation.
10430 void calc_chi(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *chi)
10431 {
10432  FTYPE kappa,kappaes;
10433  calc_kappa(pr,ptrgeom,q,&kappa);
10434  calc_kappaes(pr,ptrgeom,&kappaes);
10435 
10436  *chi=kappa+kappaes;
10437 }
10438 
10439 
10442 void calc_Tandopacityandemission(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE Ruu, FTYPE gammaradgas, FTYPE B, FTYPE *Tgas, FTYPE *Tradff, FTYPE *nradff, FTYPE *expfactorradff, FTYPE *kappa, FTYPE *kappan, FTYPE *kappaemit, FTYPE *kappanemit, FTYPE *kappaes, FTYPE *lambda, FTYPE *nlambda)
10443 {
10444  extern FTYPE calc_kappa_user(FTYPE rho, FTYPE B, FTYPE Tg,FTYPE Tr,FTYPE expfactorrad, FTYPE x,FTYPE y,FTYPE z);
10445  //user_calc_kappa()
10446 
10447  // get rho,u
10448  FTYPE rho=pr[RHO];
10449  FTYPE u=pr[UU];
10450 
10451  // get Tgas
10452  int ii=ptrgeom->i;
10453  int jj=ptrgeom->j;
10454  int kk=ptrgeom->k;
10455  int loc=ptrgeom->p;
10456  *Tgas=compute_temp_simple(ii,jj,kk,loc,rho,u);
10457  *Tgas = fabs(*Tgas) + TEMPMIN;
10458 
10459  // get Tradff and nradff
10460  calc_Trad_fromRuuandgamma(pr, ptrgeom, Ruu, gammaradgas, Tradff, nradff, expfactorradff);
10461  *Tradff = fabs(*Tradff) + TEMPMIN; // avoid division by zero in later calculations
10462  *nradff = fabs(*nradff) + SMALL;
10463 
10464  // get position for opacity if needed
10465  FTYPE V[NDIM]={0.0},xx=0.0,yy=0.0,zz=0.0;
10466 #if(ALLOWKAPPAEXPLICITPOSDEPENDENCE)
10467  bl_coord_ijk(ii,jj,kk,loc,V);
10468  xx=V[1];
10469  yy=V[2];
10470  zz=V[3];
10471 #endif
10472 
10473 
10474 #if(WHICHFIT==ISFITNEW)
10475  // get opacities
10476  // calc_kappaall_user(rho,B,*Tgas,*Tradff,*expfactorradff,xx,yy,zz, kappa, kappaemit, kappan, kappanemit, kappaes);
10477 
10478 #if(EOMRADTYPE!=EOMRADNONE)
10479  kappa_func_fits_all(rho, B, *Tgas, *Tradff, *expfactorradff, kappa, kappaemit, kappan, kappanemit, kappaes);
10480 #endif
10481 
10482 
10483  // energy density loss rate integrated over frequency and solid angle, based upon those processes written as an opacity
10484  // below lambda and nlambda now generally true
10485  *lambda = (*kappaemit)*calc_LTE_EfromT(*Tradff);
10486 
10487 #if(EVOLVENRAD)
10488  *nlambda = (*kappanemit)*calc_LTE_NfromT(*Tradff);
10489 #endif
10490 
10491 #else // WHICHFIT==ISFITORIG
10492  // get scattering opacity (elastic with no detailed energy or number weighting)
10493  *kappaes = calc_kappaes_user(rho,*Tgas,xx,yy,zz);
10494 
10495  // get energy-based absorption opacity
10496  *kappa = calc_kappa_user(rho,B,*Tgas,*Tradff,*expfactorradff,xx,yy,zz);
10497 
10498  // get energy-based emission opacity
10499  // *kappaemit = calc_kappa_user(rho,B,*Tgas,*Tgas,xx,yy,zz); // Here Trad was set to Tgas for emission of radiation
10500  *kappaemit = calc_kappaemit_user(rho,B,*Tgas,*Tradff,*expfactorradff,xx,yy,zz);
10501 
10502  // This is aT^4/(4\pi) that is the specific black body emission rate in B_\nu d\nu d\Omega corresponding to energy density rate per unit frequency per unit solid angle, which has been integrated over frequency.
10503  // More generally, kappa*4*Pi*B can be replaced by some \Lambda that is some energy density rate
10504  // But, have to be careful that "kappa rho" is constructed from \Lambda/(u*c) or else balance won't occur.
10505  // This is issue because "kappa" is often frequency integrated directly, giving different answer than frequency integrating j_v -> \Lambda/(4\pi) and B_\nu -> (aT^4)/(4\pi) each and then taking the ratio.
10506  // Note if T is near maximum for FTYPE, then aradT^4 likely too large.
10507  // FTYPE B=0.25*ARAD_CODE*pow(Tgas,4.)/Pi;
10508 
10509  // energy density loss rate integrated over frequency and solid angle, based upon those processes written as an opacity
10510  *lambda = (*kappaemit)*calc_LTE_EfromT(*Tradff); //(4.*Pi*B); / i.e. 4\pi B = arad Trad^4
10511 
10512 
10513 #if(EVOLVENRAD)
10514  // get number-based absorption opacity
10515  *kappan = calc_kappan_user(rho,B,*Tgas,*Tradff,*expfactorradff,xx,yy,zz);
10516  // get number-based emission opacity
10517  // *kappanemit = calc_kappan_user(rho,B,*Tgas,*Tgas,xx,yy,zz); // Here Trad was set to Tgas for emission of radiation
10518  *kappanemit = calc_kappanemit_user(rho,B,*Tgas,*Tradff,*expfactorradff,xx,yy,zz);
10519 
10520  // ASSUMPTION: Emitting radiation has average photon energy for gas at temperatures Tgas (isn't true for synchrotron, for example)
10521  // FTYPE ebar = EBAR0 * (TEMPMIN+*Tgas);
10522  // // result based upon opacity-based calculation of lambda, so includes free-free, bound-free, bound-bound, etc.
10523  // *nlambda = (*lambda)/ebar;
10524  *nlambda = (*kappanemit)*calc_LTE_NfromT(*Tradff);
10525 #endif
10526 
10527 
10528 #endif
10529 
10530 
10531 
10532  if(AVOIDTAUFORFLOOR==1){
10533  FTYPE bsq=B*B;
10534  FTYPE bsqorholimit=10.0; //BSQORHOLIMIT/5.0;
10535  FTYPE factor;
10536  FTYPE thebsqorho=bsq/rho;
10537  if(bsq/rho<0 || bsq/rho>BSQORHOLIMIT) thebsqorho=BSQORHOLIMIT;
10538  factor=exp(-thebsqorho/bsqorholimit);
10539 
10540  *kappaes *= factor;
10541  *kappa *= factor;
10542  *kappaemit *= factor;
10543  *lambda *= factor;
10544 
10545  *kappan *= factor;
10546  *kappanemit *= factor;
10547  *nlambda *= factor;
10548  }
10549 
10550 
10551 
10552 
10553 
10554  // dualfprintf(fail_file,"kappaabs=%g kappaes=%g\n",*kappa,*kappaes);
10555 }
10556 
10557 
10559 static void calc_Gd(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q ,FTYPE *GG, FTYPE *Tgas, FTYPE *Trad, FTYPE* chieffreturn, FTYPE *ndotffreturn, FTYPE *ndotffabsreturn, FTYPE *Gabs)
10560 {
10561  calc_Gu(pp, ptrgeom, q, GG, Tgas, Trad, chieffreturn,ndotffreturn,ndotffabsreturn,Gabs);
10562  indices_21(GG, GG, ptrgeom);
10563 }
10564 
10565 
10566 
10568 void koral_source_rad_calc(int computestate, int computeentropy, FTYPE *pr, struct of_geom *ptrgeom, FTYPE *Gdpl, FTYPE *Gdplabs, FTYPE *chi, FTYPE *Tgas, FTYPE *Trad, struct of_state *q)
10569 {
10570  int jj;
10571  int pliter,pl;
10572  FTYPE Gd[NDIM],Gdabs[NDIM];
10573  FTYPE ndotff,ndotffabs;
10574  struct of_state qlocal;
10575  FTYPE chilocal,Tgaslocal,Tradlocal;
10576 
10577  if(q==NULL){ q=&qlocal; computestate=1; }
10578  if(chi==NULL) chi=&chilocal;
10579  if(Tgas==NULL) Tgas=&Tgaslocal;
10580  if(Trad==NULL) Trad=&Tradlocal;
10581 
10582 
10584  //
10585  // energy-momentum density rate in lab-frame
10586  //
10588  // no, thermodynamics stuff can change since MHD fluid U changes, so must do get_state() as above
10589  // get_state_uconucovonly(pr, ptrgeom, q);
10590  // get_state_uradconuradcovonly(pr, ptrgeom, q);
10591  if(computestate) get_state(pr,ptrgeom,q);
10592 
10593  calc_Gd(pr, ptrgeom, q, Gd, Tgas, Trad, chi, &ndotff, &ndotffabs, Gdabs);
10594 
10595  PLOOP(pliter,pl) Gdpl[pl] = 0.0;
10596  // equal and opposite forces on fluid and radiation due to radiation 4-force
10597  //
10598  // f[pl] = ((uu[pl] - uu0[pl]) + (sign[pl] * localdt * Gdpl[pl]))*extrafactor[pl]; -> T^t_t[new] = T^t_t[old] - Gdpl[UU] -> dT^t_t = -Gdpl = Gd and so dR^t_t = -Gdpl = -Gd
10599 
10600 
10601 #define SIGNGD (1.0)
10602  // keep SIGNGD as 1.0. Just apply signgd2 in front of Gdpl in other places.
10603  // sign fixed-linked as + for URAD0 case.
10604  DLOOPA(jj) Gdpl[UU+jj] = -SIGNGD*Gd[jj];
10605  DLOOPA(jj) Gdpl[URAD0+jj] = +SIGNGD*Gd[jj];
10606 
10607  if(Gdplabs!=NULL){
10608  PLOOP(pliter,pl) Gdplabs[pl] = 0.0;
10609  DLOOPA(jj) Gdplabs[UU+jj] = Gdabs[jj];
10610  DLOOPA(jj) Gdplabs[URAD0+jj] = Gdabs[jj];
10611  }
10612 
10614  //
10615  // entropy density rate -- invariant
10616  //
10618 #if(DOENTROPY!=DONOENTROPY && ENTROPY!=-100)
10619  if(computeentropy){
10620  pl=ENTROPY;
10621  // The equation is (1/\sqrt{-g})*d_\mu(\sqrt{-g} s\rho_0 u^\mu) + Gdpl[mu].ucon[mu] = 0
10622  FTYPE Gdplentropycontribs[NDIM];
10623  // -Gdpl[UU+jj] is so heating (so lowering of T^t_t to be more negative) implies increases entropy.
10624  // assumes Gpl includes kappa already with rho so that Gpl is energy per unit volume per unit time. Dividing by T (energy) gives a dimensionless thing (entropy) per unit volume.
10625  DLOOPA(jj) Gdplentropycontribs[jj] = (-Gdpl[UU+jj])*(q->ucon[jj])/(*Tgas);
10626 
10627  Gdpl[pl] = 0.0;
10628  DLOOPA(jj) Gdpl[pl] += Gdplentropycontribs[jj];
10629 
10630  if(Gdplabs!=NULL){
10631  Gdplabs[pl] = 0.0;
10632  DLOOPA(jj) Gdplabs[pl] += fabs(Gdplentropycontribs[jj]);
10633  }
10634  }
10635 #endif
10636 
10638  //
10639  // number density of photon rate -- invariant
10640  //
10642 #if(EVOLVENRAD)
10643  pl=NRAD;
10644  Gdpl[pl] = ndotff;
10645  Gdplabs[pl] = ndotffabs;
10646 #endif
10647 
10648 
10649 }
10650 
10651 
10653 static void koral_source_dtsub_rad_calc(int method, FTYPE *pr, FTYPE *Ui, FTYPE *Uf, FTYPE *dUother, FTYPE *CUf, FTYPE *CUimp, FTYPE *Gdpl, struct of_geom *ptrgeom, FTYPE *dtsub)
10654 {
10655  FTYPE Gdplabs[NPR];
10656  FTYPE chi,Tgas,Trad;
10657  struct of_state q;
10658 
10659  int computestate=1;
10660  int computeentropy=1;
10661  koral_source_rad_calc(computestate,computeentropy,pr,ptrgeom,Gdpl,Gdplabs,&chi,&Tgas,&Trad,&q);
10662 
10663  if(dtsub!=NULL){
10664  // then assume expect calculation of dtsub
10665  get_dtsub(method, pr, &q, Ui, Uf, dUother, CUf, CUimp, Gdpl, chi, Gdplabs, ptrgeom, dtsub);
10666  }
10667  // else "method" can be anything and it doesn't matter
10668 
10669 
10670 }
10671 
10672 
10674 static void calc_Gu(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q ,FTYPE *Gu, FTYPE *Tgasreturn, FTYPE *Tradreturn, FTYPE* chieffreturn, FTYPE *ndotffreturn, FTYPE *ndotffabsreturn, FTYPE *Gabs)
10675 {
10676  int i,j,k;
10677 
10678  //radiative stress tensor in the lab frame
10679  FTYPE Rij[NDIM][NDIM];
10680 
10681  //this call returns R^i_j, i.e., the first index is contra-variant and the last index is co-variant
10682  mhdfull_calc_rad(pp, ptrgeom, q, Rij);
10683 
10684  //the four-velocity of fluid in lab frame
10685  FTYPE *ucon,*ucov;
10686  ucon = q->ucon;
10687  ucov = q->ucov;
10688 
10689  //Eradff = R^a_b u_a u^b
10690  FTYPE Ruu=0.; DLOOP(i,j) Ruu+=Rij[i][j]*ucov[i]*ucon[j];
10691 
10692  // get relative Lorentz factor between gas and radiation
10693  FTYPE gammaradgas = 0.0;
10694  int jj;
10695  DLOOPA(jj) gammaradgas += - (q->ucov[jj] * q->uradcon[jj]);
10696 
10697  // get B
10698  FTYPE bsq = dot(q->bcon, q->bcov);
10699  FTYPE B=sqrt(bsq);
10700 
10701  FTYPE rho=pp[RHO];
10702 
10703  // get absorption opacities
10704  FTYPE Tgas;
10705  FTYPE Tradff,nradff,expfactorradff;
10706  FTYPE kappa,kappan;
10707  FTYPE kappaemit,kappanemit;
10708  FTYPE kappaes;
10709  FTYPE lambda,nlambda;
10710  calc_Tandopacityandemission(pp,ptrgeom,q,Ruu,gammaradgas,B,&Tgas,&Tradff,&nradff,&expfactorradff,&kappa,&kappan,&kappaemit,&kappanemit,&kappaes, &lambda, &nlambda);
10711  // get chi (absorption energy opacity total)
10712  FTYPE chi=kappa+kappaes;
10713 
10714 
10715 
10717  // compute contravariant four-force in the lab frame
10718 
10719 
10720 
10721 #if(0)
10722 
10723  // Ru^\mu = R^\mu_\nu u^\nu
10724  // Ruu = R^a_b u_a u^b
10725 
10726  // Ruuu^\mu = Ru^\mu + Ruu u^\mu
10727  // = R^\mu_c u^c + R^a_b u_a u^b u^\mu
10728 
10729  // Ruuu^t = R^t_t u^t + R^t_t u_t u^t u^t + R^t_i u^i + R^i_t u_i u^t u^t + R^t_j u_t u^j u^t
10730 
10731  // Ruuu^t = R^t_t u^t (1 + u_t u^t) + Rus + Ruuss
10732 
10733  // (1 + u_t u^t) = 1 + u^t (u^t g_{tt} + u^i g_{ti}) = 1+ u^t^2 g_{tt} + u^t u^i g_{ti} = 1 - (\gamma/\alpha)^2 (-g_{tt}) + u^t u^i g_{ti}
10734 
10735  // = 1 - (\gamma/\alpha)^2 (-(1 + g_{tt} -1)) = 1 - (\gamma/\alpha)^2 + (\gamma/\alpha)^2 (1+g_{tt})
10736 
10737  //
10738 
10739  // get R^t_t u^t + (R^t_t u^t u_t)u^t and avoid catastrophic cancellation
10740  FTYPE Ruuss=0.; DLOOP(i,j) if(i!=TT && j!=TT) Ruuss+=Rij[i][j]*ucov[i]*ucon[j];
10741  // __WORKINGONIT__: Check again.
10742  FTYPE fact=(-ptrgeom->gcov[GIND(TT,TT)])*(-ptrgeom->gcon[GIND(TT,TT)]);
10743  FTYPE fact2=1.0-fact;
10744  FTYPE utildecon[NDIM]={0.0,pp[URAD1],pp[URAD2],pp[URAD3]};
10745  FTYPE utsq = 0.0,utildecov[NDIM]; lower_vec(utildecon,ptrgeom,utildecov); SLOOPA(j) utsq+=utildecon[j]*utildecov[j];
10746  FTYPE ucontucovt = ( fact2 - utsq*fact + ucon[TT]*(ucon[1]*ptrgeom->gcov[GIND(TT,1)]+ucon[2]*ptrgeom->gcov[GIND(TT,2)]+ucon[3]*ptrgeom->gcov[GIND(TT,3)]));
10747  FTYPE Rut=Rij[TT][TT]*ucon[TT] * ucontucovt;
10748  FTYPE Rus;
10749 #endif
10750 
10751 
10752 
10753 #if(DOCOMPTON)
10754  extern FTYPE Gcompt(FTYPE rho, FTYPE Tgas, FTYPE Tradff, FTYPE Ruu);
10755  FTYPE preterm3 = Gcompt(rho,Tgas,Tradff,Ruu);
10756 #endif
10757 
10758 
10759 
10760 
10762  // LOOP over i
10763  FTYPE Ru,Ruuu,Ruuuabs,term1a,term1b,term2,term2abs,term3;
10764  DLOOPA(i){
10765  Ru=0.; DLOOPA(j) Ru+=Rij[i][j]*ucon[j];
10766 #if(1)
10767  Ruuu=(Ru + Ruu*ucon[i]);
10768  Ruuuabs=fabs(Ru) + fabs(Ruu*ucon[i]);
10769 #else
10770  if(i!=TT) Ruuu=(Ru + Ruu*ucon[i]);
10771  else{
10772  Rus=0.; DLOOPA(j) if(j!=TT) Rus+=Rij[i][j]*ucon[j];
10773  Ruuu=Ruuss + Rus + Rut;
10774  }
10775  Ruuuabs=fabs(Ru) + fabs(Ruu*ucon[i]);
10776 #endif
10777 
10778  // group by independent terms
10779  term1a = -(kappa*Ru);
10780  term1b = -(lambda*ucon[i]);
10781 
10782  term2 = -kappaes*Ruuu;
10783  term2abs = fabs(kappaes*Ruuuabs);
10784 
10785 #if(DOCOMPTON)
10786  term3 = preterm3*ucon[i]; // ASSUMPTION: in fluid frame only energy exchange, no momentum exchange.
10787 #else
10788  term3 = 0.0;
10789 #endif
10790 
10791  // actual source term
10792  // Gu[i]=-chi*Ru - (kappaes*Ruu + lambda)*ucon[i] + term3;
10793  Gu[i] = term1a + term1b + term2 + term3;
10794 
10795  // absolute magnitude of source term that can be used for estimating importance of 4-force relative to existing conserved quantities to get dtsub. But don't split kappa terms because if those cancel then physically no contribution.
10796  Gabs[i] = fabs(term1a) + fabs(term1b) + fabs(term2abs) + fabs(term3);
10797 
10798 #if(0)
10799  // DEBUG:
10800  if(ptrgeom->i==3 && ptrgeom->j==26){
10801  dualfprintf(fail_file,"i=%d term1a=%g term1b=%g term2=%g kappa=%g lambda=%g kappaes=%g ucon=%g Gu=%g Gabs=%g\n",i,term1a,term1b,term2,kappa,lambda,kappaes,ucon[i],Gu[i],Gabs[i]);
10802  }
10803 #endif
10804 
10805  }// END LOOP over ENERGY-MOMENTUM terms
10806 
10807 
10808 
10809 
10810  // return some other things that may be useful beyond Gu and Gabs
10811  *Tgasreturn=Tgas;
10812  *Tradreturn=Tradff;
10813  // *expfactorradreturn=expfactorradff; // not used in return (yet)
10814  // really a chi-effective that also includes lambda term in case cooling unrelated to absorption
10815  *chieffreturn=chi + lambda/(ERADLIMIT+fabs(pp[PRAD0])); // if needed
10816 
10817 
10818 
10819 
10820 
10821  // get photon number source term, dnrad/dtau in comoving frame, which acts as source term.
10822 #if(EVOLVENRAD&&NRAD>0)
10823  FTYPE ndotff,ndotffabs;
10824  // in limit that Tgas=Trad, must have balance such that ndotff->0, so nlambda must come from kappan and nradff->LTE_N
10825  ndotff = -(kappan*nradff - nlambda);
10826  ndotffabs = fabs(kappan*nradff) + fabs(nlambda);
10827  // return \dot{nrad} : photon density in fluid frame per unit fluid frame time
10828  *ndotffreturn=ndotff;
10829  *ndotffabsreturn=ndotffabs;
10830 #endif
10831 
10832 
10833 
10834 
10835 }
10836 
10837 
10838 // compute Trad with only primitive sand geometry
10839 static void calcfull_Trad(FTYPE *pp, struct of_geom *ptrgeom, FTYPE *Trad, FTYPE *nrad, FTYPE *expfactorrad)
10840 {
10841 
10842  struct of_state q;
10843  get_state(pp, ptrgeom, &q);
10844  calc_Trad(pp,ptrgeom,&q,Trad,nrad,expfactorrad);
10845 
10846 }
10847 
10848 
10850 static void calc_Trad(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q , FTYPE *Trad, FTYPE *nrad, FTYPE *expfactorrad)
10851 {
10852  int i,j,k;
10853  FTYPE Tradff,nradff,expfactorradff;
10854 
10855  if(q==NULL){// if q==NULL, assume don't want to do something expensive an accurate, just basics
10856  // so get radiation frame things even if should have gotten fluid frame things
10857  //get_state(pp, ptrgeom, &q);
10858  Tradff = calc_LTE_TfromE(pp[PRAD0]);
10859  nradff = calc_LTE_NfromE(pp[PRAD0]);
10860  expfactorradff=1.0;
10861  }
10862  else{
10863 
10864  FTYPE rho=pp[RHO];
10865 
10866  //radiative stress tensor in the lab frame
10867  FTYPE Rij[NDIM][NDIM];
10868 
10869  //this call returns R^i_j, i.e., the first index is contra-variant and the last index is co-variant
10870  mhdfull_calc_rad(pp, ptrgeom, q, Rij);
10871 
10872  //the four-velocity of fluid in lab frame
10873  FTYPE *ucon,*ucov;
10874  ucon = q->ucon;
10875  ucov = q->ucov;
10876 
10877  // Get fluid-frame radiation energy density = Eradff = R^a_b u_a u^b
10878  FTYPE Ruu=0.; DLOOP(i,j) Ruu+=Rij[i][j]*ucov[i]*ucon[j];
10879  FTYPE gammaradgas = 0.0;
10880  int jj;
10881  DLOOPA(jj) gammaradgas += - (q->ucov[jj] * q->uradcon[jj]);
10882 
10883  calc_Trad_fromRuuandgamma(pp, ptrgeom, Ruu, gammaradgas, &Tradff, &nradff, &expfactorradff);
10884  }
10885 
10886  // return quantities
10887  *Trad=Tradff; // radiation temperature in fluid frame
10888  *nrad=nradff; // radiation number density in fluid frame
10889  *expfactorrad=expfactorradff;
10890 }
10891 
10892 
10894 static void calc_Trad_fromRuuandgamma(FTYPE *pp, struct of_geom *ptrgeom, FTYPE Ruu, FTYPE gammaradgas, FTYPE *Trad, FTYPE *nrad, FTYPE *expfactorrad)
10895 {
10896  FTYPE Tradff,nradff,expfactorradff;
10897 
10898  // Get fluid-frame radiation temperature and number density
10899 
10900 
10901 
10902 #if(EVOLVENRAD==0)
10903  // ASSUMPTION: PLANCK
10904  Tradff = calc_LTE_TfromE(fabs(Ruu));
10905  nradff = calc_LTE_NfromE(fabs(Ruu));
10906  expfactorradff=1.0; // Planck
10907 #else
10908  // Color-corrected/shifted Planck
10909  nradff = pp[NRAD]*gammaradgas;
10910 
10911  // 0 = assume 0 chemical potential.
10912  // 1 = account for finite chemical potential using Ramesh fit
10913  // 2 = like 1 but Jon fit without divergent issues.
10914  // But 1,2 only change T_r by 10% at most for any Ruu,nradff, and would have to include chemical potential in opacity and use (say Jon's) chemical potential vs. Ruu,nradff fit and have \kappa(Tg,Tr,\mu). So avoid.
10915 #define TRADTYPE 0
10916 
10917 #if(TRADTYPE==0)
10918  Tradff = Ruu/(nradff*EBAR0); // EBAR0 kb T = Ruu/nradff = average energy per photon
10919  expfactorradff = 1.0; // but really inconsistent since should be able to get Tradff directly from Ruu if \mu=0
10920 #elif(TRADTYPE==1)
10921  FTYPE CRAD = CRAD0*ARAD_CODE;
10922  FTYPE BB = CRAD0 * EBAR0*EBAR0*EBAR0*EBAR0 * (3.0-EBAR0); // FTYPE BB=2.449724;
10923  // below avoids assuming that EBAR0 kb T is average energy per photon
10924  FTYPE EBAR1=3.0-BB*nradff*nradff*nradff*nradff/(CRAD*Ruu*Ruu*Ruu+SMALL); // physically reasonable to be limited to *larger* than EBAR0
10925  if(EBAR1<EBAR0) EBAR1=EBAR0; // hard cut
10926  //if(EBAR1<0.5*EBAR0) EBAR1=0.5*EBAR0; // hard cut but at lower value, allowing a bit lower than BB value that is rare but avoids Jacobian problems
10927  Tradff = Ruu/(SMALL+nradff*EBAR1); // Accounts for non-zero chemical potential of photons giving them higher average energy per photon than thermal case for a given temperature
10928 #elif(TRADTYPE==2)
10929  Tradff = (Ruu*(0.333333333327962 + 0.060724957534625555/(0.6467556546674441 + (0.12198190033984817*CRAD*Power(Ruu,3))/Power(SMALL+nradff,4))))/(SMALL+nradff);
10930  expfactorradff = 1.6467556546674442/(0.6467556546674441 + (0.12198190033984817*CRAD*Power(Ruu,3))/Power(SMALL+nradff,4));
10931  if(expfactorradff>1.0) expfactorradff=1.0; // account for BE condensation.
10932  // expfactorradff = exp(-\xi) = exp(-\mu/(k_B Tradff))
10933 #endif
10934  // Tradff/TradLTE = fco = color correction factor
10935 
10936 #endif
10937 
10938  *Trad=Tradff; // radiation temperature in fluid frame
10939  *nrad=nradff; // radiation number density in fluid frame
10940  *expfactorrad=expfactorradff;// expf = e^{-\mu/(k_b T_r)} for chemical potential mu of radiation
10941 }
10942 
10943 
10944 
10945 
10946 
10947 
10948 
10949 
10950 
10951 // compute approximate dRtt/Rtt based upon all source terms to be used to compare ratchangeRtt*uu vs. NUMEPSILON*uuallabs or idtsub=ratchangeRtt/realdt gives dtsub<realdt
10952 static FTYPE calc_approx_ratchangeRtt(struct of_state *q, FTYPE chieff, FTYPE realdt)
10953 {
10954 
10955  // New Jon method (problem is this only makes sense in perfectly LTE. If T gets high quickly, then G gets high before the density reacts.)
10956  // this is like having a "source speed" of v_s\sim \tau \gamma^2 c and limiting the timestep so the source wave only reaches across a cell dxortho in time dt.
10957 
10958 
10959  // as due to non-Compton 4-force
10960  FTYPE ucon0=q->ucon[TT]; // what enters G for dR^t_t/R^t_t from time part
10961  FTYPE ratchangeRtt=SMALL+fabs(chieff * ucon0 * ucon0 * realdt * 1.0); // 1.0 = c (2nd term with chi instead of kappaes to be severe and account for B-based term)
10962 
10963  // assume Compton term good enough with Gabs
10964 
10965 
10966  return(ratchangeRtt);
10967 
10968 }
10969 
10970 
10971 
10972 
10973 
10975 int vchar_rad(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *vmax, FTYPE *vmin, FTYPE *vmax2, FTYPE *vmin2,int *ignorecourant)
10976 {
10977 
10978 
10979  // compute chi
10980  // Assume computed as d\tau/dorthonormallength as defined by user.
10981  // Assume \chi defined in fluid frame (i.e. not radiation frame).
10982  FTYPE kappa,chi;
10983  calc_chi(pr,geom,q,&chi);
10984  // KORALTODO: in paper, suggests only kappaes should matter?
10985  // calc_kappa(pr,geom,q,&kappa);
10986  // chi=kappa;
10987 
10988 
10989  //characterisitic wavespeed in the radiation rest frame
10990  FTYPE vrad2=THIRD;
10991  FTYPE vrad2limited;
10992 
10993  if(chi>0.0){// && WHICHRADSOURCEMETHOD==SOURCEMETHODIMPLICIT){
10994  // NOT DOING THIS:
10995  // compute tautot assuming chi is optical depth per unit grid dx[1-3]. I.e. calc_chi() computes grid-based opacity
10996  // tautot is the total optical depth of the cell in dim dimension
10997  // tautot = chi * dx[dir];
10998 
10999  // DOING THIS:
11000  // KORALTODO: Approximation to any true path, but approximation is sufficient for approximate wave speeds.
11001  // \tau_{\rm tot}^2 \approx \chi^2 [dxff^{dir} \sqrt{g_{dirdir}}]^2 where dxff is dx in fluid-frame where chi is measured
11002  FTYPE tautotsq,vrad2tau;
11003  // Note that tautot is frame independent once multiple \chi by the cell length. I.e. it's a Lorentz invariant.
11004  FTYPE tautot[NDIM];
11005  FTYPE tautotmax;
11006  calc_tautot_chieff(pr, chi, geom, q, tautot, &tautotmax);
11007  tautotsq = tautot[dir]*tautot[dir];
11008 
11009  // below previous version was not Lorentz invariant.
11010  // tautotsq = chi*chi * dx[dir]*dx[dir]*fabs(geom->gcov[GIND(dir,dir)]);
11011 
11012  // dualfprintf(fail_file,"chi=%g dx=%g dir=%d tautot=%g\n",chi,dx[dir],dir,sqrt(tautotsq));
11013 
11014  vrad2tau=(4.0/3.0)*(4.0/3.0)/tautotsq; // KORALTODO: Why 4.0/3.0 ? Seems like it should be 2.0/3.0 according to NR1992 S19.2.6L or NR2007 S20.2L with D=1/(3\chi), but twice higher speed is only more robust.
11015  vrad2limited=MIN(vrad2,vrad2tau);
11016 
11017  // NOTEMARK: For explicit method, this will lead to very large dt relative to step desired by explicit method, leading to ever more sub-cycles for WHICHRADSOURCEMETHOD==SOURCEMETHODEXPLICITSUBCYCLE method.
11018 
11019  // TODOMARK: I wonder if another possibility is to use a speed limiter in the advection equation.  With my pseudo-Newtonian code is has a limiter on the sound and Alfven speeds following the idea of limiting the Alfven speed by Miller & Stone (2000, http://adsabs.harvard.edu/abs/2000ApJ...534..398M).  That is, there must be a way to insert a term into the radiation advection equations to limit the velocity to ~c/\tau that only becomes effective at and beyond that speed.  Then the Jacobian would be modified (Or thinking of how the Jacobian could get modified, one gets a different equation of motion).
11020 
11021  }
11022  else{
11023  vrad2limited=vrad2;
11024  }
11025 
11026 
11027  // for setting flux so diffusive term is not exaggerated in high \tau regions
11028  simplefast_rad(dir,geom,q,vrad2limited,vmin,vmax);
11029 
11030 
11031  if(FORCESOLVELFLUX){
11032  FTYPE ftemp=1.0/sqrt(fabs(geom->gcov[GIND(dir,dir)]));
11033  *vmin=-ftemp;
11034  *vmax=+ftemp;
11035  }
11036  // cminmaxrad_l[CMIN]=-ftemp;
11037  // cminmaxrad_l[CMAX]=+ftemp;
11038  // cminmax_calc(cminmaxrad_l[CMIN],cminmaxrad_r[CMIN],cminmaxrad_l[CMAX],cminmaxrad_r[CMAX],&cminmaxrad[CMIN],&cminmaxrad[CMAX],ctopradptr);
11039  // ctoprad=ftemp;
11040 
11041 #if(1)
11042  *vmin2=*vmin;
11043  *vmax2=*vmax;
11044 #elif(0)
11045  // for setting timestep since advective part has no knowledge of \tau-limited velocity
11046  simplefast_rad(dir,geom,q,vrad2,vmin2,vmax2);
11047 #else
11048  // works even if not using damping of implicit solver
11049  simplefast_rad(dir,geom,q,2.0/3.0,vmin2,vmax2);
11050 #endif
11051 
11052 
11053  return(0);
11054 }
11055 
11057 static int simplefast_rad(int dir, struct of_geom *geom,struct of_state *q, FTYPE vrad2,FTYPE *vmin, FTYPE *vmax)
11058 {
11059  extern int simplefast(int whichcall, int dir, struct of_geom *geom,struct of_state *q, FTYPE cms2,FTYPE *vmin, FTYPE *vmax);
11060 
11061  //need to substitute ucon,ucov with uradcon,uradcov to fool simplefast
11062  FTYPE ucon[NDIM],ucov[NDIM];
11063  int ii;
11064  DLOOPA(ii){
11065  ucon[ii]=q->ucon[ii];
11066  ucov[ii]=q->ucov[ii];
11067  q->ucon[ii]=q->uradcon[ii];
11068  q->ucov[ii]=q->uradcov[ii];
11069  }
11070 
11071  //calculating vmin, vmax
11072  simplefast(0, dir,geom,q,vrad2,vmin,vmax); // simplefast(0) means first call rather than an resursive attempt.
11073 
11074  //restoring gas 4-velocities
11075  DLOOPA(ii){
11076  q->ucon[ii]=ucon[ii];
11077  q->ucov[ii]=ucov[ii];
11078  }
11079 
11080 
11081 #if(0)
11082  // Cartesian-Minkowski speed-of-light limit of radiation velocity
11083  FTYPE dxdxp[NDIM][NDIM];
11084  dxdxprim_ijk(geom->i, geom->j, geom->k, geom->p, dxdxp);
11085  // characeristic wavespeeds are 3-velocity in lab-frame
11086  *vmin=-1.0/dxdxp[dir][dir]; // e.g. dxdxp = dr/dx1
11087  *vmax=+1.0/dxdxp[dir][dir];
11088 #endif
11089 
11090 
11091  return(0);
11092 }
11093 
11094 
11096 int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
11097 {
11098  void compute_1plusud0(FTYPE *pr, struct of_geom *geom, struct of_state *q, FTYPE *plus1ud0); // plus1ud0=(1+q->ucov[TT])
11099 
11100  // urad^\mu
11101  // ucon_calc() assumes primitive velocities are in U1 through U3, but otherwise calculation is identical for radiation velocity, so just shift effective list of primitives so ucon_calc() operates on U1RAD through U3RAD
11102  MYFUN(ucon_calc(&pr[URAD1-U1], ptrgeom, q->uradcon,q->othersrad) ,"phys.c:get_state()", "ucon_calc()", 1);
11103  // urad_\mu
11104  lower_vec(q->uradcon, ptrgeom, q->uradcov);
11105 
11106 
11107  return (0);
11108 }
11109 
11110 
11111 void mhdfull_calc_rad(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE (*radstressdir)[NDIM])
11112 {
11113  int jj,kk;
11114 
11115  if(EOMRADTYPE!=EOMRADNONE){
11116  DLOOPA(jj){
11117  mhd_calc_rad( pr, jj, ptrgeom, q, &(radstressdir[jj][0]) , NULL );
11118  }
11119  }
11120  else DLOOP(jj,kk) radstressdir[jj][kk]=0.0; // mhd_calc_rad() called with no condition in phys.tools.c and elsewhere, and just fills normal tempo-spatial components (not RAD0->RAD3), so need to ensure zero.
11121 }
11122 
11124 void mhd_calc_rad(FTYPE *pr, int dir, struct of_geom *ptrgeom, struct of_state *q, FTYPE *radstressdir, FTYPE *radstressdirabs)
11125 {
11126  int jj;
11127  FTYPE term1[NDIM],term2[NDIM];
11128 
11129  // R^{dir}_{jj} radiation stress-energy tensor
11130  if(EOMRADTYPE==EOMRADEDD){
11131  // force radiation frame to be fluid frame
11132  DLOOPA(jj){
11133  term1[jj]=THIRD*pr[PRAD0]*(4.0*q->ucon[dir]*q->ucov[jj]);
11134  term2[jj]=THIRD*pr[PRAD0]*(delta(dir,jj));
11135  radstressdir[jj]=term1[jj]+term2[jj];
11136  if(radstressdirabs!=NULL) radstressdirabs[jj]=fabs(term1[jj])+fabs(term2[jj]);
11137  }
11138  }
11139  else if(EOMRADTYPE==EOMRADM1CLOSURE){
11140  DLOOPA(jj){
11141  term1[jj]=THIRD*pr[PRAD0]*(4.0*q->uradcon[dir]*q->uradcov[jj]);
11142  term2[jj]=THIRD*pr[PRAD0]*(delta(dir,jj));
11143  radstressdir[jj]=term1[jj]+term2[jj];
11144  if(radstressdirabs!=NULL) radstressdirabs[jj]=fabs(term1[jj])+fabs(term2[jj]);
11145  }
11146  }
11147  else{
11148  // mhd_calc_rad() called with no condition in phys.tools.c and elsewhere, and just fills normal tempo-spatial components (not RAD0->RAD3), so need to ensure zero.
11149  DLOOPA(jj){
11150  radstressdir[jj]=0.0;
11151  if(radstressdirabs!=NULL) radstressdirabs[jj]=0.0;
11152  }
11153  }
11154 
11155 
11156 }
11157 
11159 int calc_Rij_ff(FTYPE *pp, FTYPE Rij[][NDIM])
11160 {
11161  FTYPE E=pp[PRAD0];
11162  FTYPE F[NDIM-1]={pp[PRAD1],pp[PRAD2],pp[PRAD3]};
11163 
11164  FTYPE nx,ny,nz,nlen,f;
11165 
11166  nx=F[0]/E;
11167  ny=F[1]/E;
11168  nz=F[2]/E;
11169  nlen=sqrt(nx*nx+ny*ny+nz*nz);
11170 
11171 
11172  if(EOMRADTYPE==EOMRADEDD){
11173  f=1./3.; // f and Rij are both as if nx=ny=nz=0
11174  // f=(3.+4.*(nx*nx+ny*ny+nz*nz))/(5.+2.*sqrt(4.-3.*(nx*nx+ny*ny+nz*nz)));
11175  }
11176  else if(EOMRADTYPE==EOMRADM1CLOSURE){
11177 
11178  if(nlen>=1.) f=1.; // KORALTODO: limiter, but only used so far for IC
11179  else f=(3.+4.*(nx*nx+ny*ny+nz*nz))/(5.+2.*sqrt(4.-3.*(nx*nx+ny*ny+nz*nz))); //M1
11180  }
11181  else if(EOMRADTYPE==EOMRADNONE){
11182 
11183  }
11184  else{
11185  dualfprintf(fail_file,"1 No Such EOMRADTYPE=%d\n",EOMRADTYPE);
11186  myexit(837453242);
11187  }
11188 
11190  Rij[0][0]=E;
11191 
11192  if(EOMRADTYPE==EOMRADEDD){
11193  // KORALTODO: Below 3 should be zero for Eddington approximation, but only if F=0 exactly.
11194  Rij[0][1]=Rij[1][0]=0.0;
11195  Rij[0][2]=Rij[2][0]=0.0;
11196  Rij[0][3]=Rij[3][0]=0.0;
11197  }
11198  else if(EOMRADTYPE==EOMRADM1CLOSURE){
11199  Rij[0][1]=Rij[1][0]=F[0];
11200  Rij[0][2]=Rij[2][0]=F[1];
11201  Rij[0][3]=Rij[3][0]=F[2];
11202  }
11203  else if(EOMRADTYPE==EOMRADNONE){
11204 
11205  }
11206  else{
11207  dualfprintf(fail_file,"2 No Such EOMRADTYPE=%d\n",EOMRADTYPE);
11208  myexit(837453243);
11209  }
11210 
11211 
11212  // normalize n^i for Rij calculation
11213  if(nlen>0){
11214  nx/=nlen;
11215  ny/=nlen;
11216  nz/=nlen;
11217  }
11218  else{
11219  ;
11220  }
11221 
11222  Rij[1][1]=E*(.5*(1.-f) + .5*(3.*f - 1.)*nx*nx);
11223  Rij[1][2]=E*(.5*(3.*f - 1.)*nx*ny);
11224  Rij[1][3]=E*(.5*(3.*f - 1.)*nx*nz);
11225 
11226  Rij[2][1]=E*(.5*(3.*f - 1.)*ny*nx);
11227  Rij[2][2]=E*(.5*(1.-f) + .5*(3.*f - 1.)*ny*ny);
11228  Rij[2][3]=E*(.5*(3.*f - 1.)*ny*nz);
11229 
11230  Rij[3][1]=E*(.5*(3.*f - 1.)*nz*nx);
11231  Rij[3][2]=E*(.5*(3.*f - 1.)*nz*ny);
11232  Rij[3][3]=E*(.5*(1.-f) + .5*(3.*f - 1.)*nz*nz);
11233 
11234  return 0;
11235 }
11236 
11237 
11238 
11240 {
11241  if(aa<bb) return aa;
11242  else return bb;
11243 }
11244 
11246 {
11247  if(x>0.) return 1.;
11248  if(x<0.) return -1.;
11249  if(x==0.) return 0.;
11250  return 0;
11251 }
11252 
11253 
11254 
11255 
11261 int inverse_44matrix(FTYPE aa[][NDIM], FTYPE ia[][NDIM])
11262 {
11263  FTYPE mat[16],dst[16];
11264  int i,j;
11265  for(i=0;i<4;i++)
11266  for(j=0;j<4;j++)
11267  mat[i*4+j]=aa[i][j];
11268 
11269  FTYPE tmp[12]; FTYPE src[16]; FTYPE det, idet;
11270  /* transpose matrix */
11271  for (i = 0; i <4; i++)
11272  {
11273  src[i]=mat[i*4];
11274  src[i+4]=mat[i*4+1];
11275  src[i+8]=mat[i*4+2];
11276  src[i+12]=mat[i*4+3];
11277  }
11278  /* calculate pairs for first 8 elements (cofactors) */
11279  tmp[0] = src[10] * src[15];
11280  tmp[1] = src[11] * src[14];
11281  tmp[2] = src[9] * src[15];
11282  tmp[3] = src[11] * src[13];
11283  tmp[4] = src[9] * src[14];
11284  tmp[5] = src[10] * src[13];
11285  tmp[6] = src[8] * src[15];
11286  tmp[7] = src[11] * src[12];
11287  tmp[8] = src[8] * src[14];
11288  tmp[9] = src[10] * src[12];
11289  tmp[10] = src[8] * src[13];
11290  tmp[11] = src[9] * src[12];
11291  /* calculate first 8 elements (cofactors) */
11292  dst[0] = tmp[0]*src[5] + tmp[3]*src[6] + tmp[4]*src[7];
11293  dst[0] -= tmp[1]*src[5] + tmp[2]*src[6] + tmp[5]*src[7];
11294  dst[1] = tmp[1]*src[4] + tmp[6]*src[6] + tmp[9]*src[7];
11295  dst[1] -= tmp[0]*src[4] + tmp[7]*src[6] + tmp[8]*src[7];
11296  dst[2] = tmp[2]*src[4] + tmp[7]*src[5] + tmp[10]*src[7];
11297  dst[2] -= tmp[3]*src[4] + tmp[6]*src[5] + tmp[11]*src[7];
11298  dst[3] = tmp[5]*src[4] + tmp[8]*src[5] + tmp[11]*src[6];
11299  dst[3] -= tmp[4]*src[4] + tmp[9]*src[5] + tmp[10]*src[6];
11300  dst[4] = tmp[1]*src[1] + tmp[2]*src[2] + tmp[5]*src[3];
11301  dst[4] -= tmp[0]*src[1] + tmp[3]*src[2] + tmp[4]*src[3];
11302  dst[5] = tmp[0]*src[0] + tmp[7]*src[2] + tmp[8]*src[3];
11303  dst[5] -= tmp[1]*src[0] + tmp[6]*src[2] + tmp[9]*src[3];
11304  dst[6] = tmp[3]*src[0] + tmp[6]*src[1] + tmp[11]*src[3];
11305  dst[6] -= tmp[2]*src[0] + tmp[7]*src[1] + tmp[10]*src[3];
11306  dst[7] = tmp[4]*src[0] + tmp[9]*src[1] + tmp[10]*src[2];
11307  dst[7] -= tmp[5]*src[0] + tmp[8]*src[1] + tmp[11]*src[2];
11308  /* calculate pairs for second 8 elements (cofactors) */
11309  tmp[0] = src[2]*src[7];
11310  tmp[1] = src[3]*src[6];
11311  tmp[2] = src[1]*src[7];
11312  tmp[3] = src[3]*src[5];
11313  tmp[4] = src[1]*src[6];
11314  tmp[5] = src[2]*src[5];
11315  tmp[6] = src[0]*src[7];
11316  tmp[7] = src[3]*src[4];
11317  tmp[8] = src[0]*src[6];
11318  tmp[9] = src[2]*src[4];
11319  tmp[10] = src[0]*src[5];
11320  tmp[11] = src[1]*src[4];
11321  /* calculate second 8 elements (cofactors) */
11322  dst[8] = tmp[0]*src[13] + tmp[3]*src[14] + tmp[4]*src[15];
11323  dst[8] -= tmp[1]*src[13] + tmp[2]*src[14] + tmp[5]*src[15];
11324  dst[9] = tmp[1]*src[12] + tmp[6]*src[14] + tmp[9]*src[15];
11325  dst[9] -= tmp[0]*src[12] + tmp[7]*src[14] + tmp[8]*src[15];
11326  dst[10] = tmp[2]*src[12] + tmp[7]*src[13] + tmp[10]*src[15];
11327  dst[10]-= tmp[3]*src[12] + tmp[6]*src[13] + tmp[11]*src[15];
11328  dst[11] = tmp[5]*src[12] + tmp[8]*src[13] + tmp[11]*src[14];
11329  dst[11]-= tmp[4]*src[12] + tmp[9]*src[13] + tmp[10]*src[14];
11330  dst[12] = tmp[2]*src[10] + tmp[5]*src[11] + tmp[1]*src[9];
11331  dst[12]-= tmp[4]*src[11] + tmp[0]*src[9] + tmp[3]*src[10];
11332  dst[13] = tmp[8]*src[11] + tmp[0]*src[8] + tmp[7]*src[10];
11333  dst[13]-= tmp[6]*src[10] + tmp[9]*src[11] + tmp[1]*src[8];
11334  dst[14] = tmp[6]*src[9] + tmp[11]*src[11] + tmp[3]*src[8];
11335  dst[14]-= tmp[10]*src[11] + tmp[2]*src[8] + tmp[7]*src[9];
11336  dst[15] = tmp[10]*src[10] + tmp[4]*src[8] + tmp[9]*src[9];
11337  dst[15]-= tmp[8]*src[9] + tmp[11]*src[10] + tmp[5]*src[8];
11338  /* calculate determinant */
11339  det=src[0]*dst[0]+src[1]*dst[1]+src[2]*dst[2]+src[3]*dst[3];
11340 
11341 
11342  /* calculate matrix inverse */
11343  idet = 1.0/det;
11344 
11345  // if(isnan(idet)){
11346  if(!isfinite(idet) || !isfinite(det)){
11347  if(debugfail>=2) dualfprintf(fail_file,"idet (det=%26.15g idet=%26.15g) in inverse 4x4 zero or nan\n",det,idet);
11348  return(1); // indicates failure
11349  // myexit(13235);
11350  }
11351 
11352  for (j = 0; j < 16; j++)
11353  dst[j] *= idet;
11354 
11355  for(i=0;i<4;i++)
11356  for(j=0;j<4;j++)
11357  ia[i][j]= dst[i*4+j];
11358 
11359  return 0;
11360 }
11361 
11362 
11363 
11369 static int inverse_33matrix(int sj, int ej, FTYPE aa[][NDIM], FTYPE ia[][NDIM])
11370 {
11371 
11372  FTYPE det = +aa[sj+0][sj+0]*(aa[sj+1][sj+1]*aa[sj+2][sj+2]-aa[sj+2][sj+1]*aa[sj+1][sj+2])
11373  -aa[sj+0][sj+1]*(aa[sj+1][sj+0]*aa[sj+2][sj+2]-aa[sj+1][sj+2]*aa[sj+2][sj+0])
11374  +aa[sj+0][sj+2]*(aa[sj+1][sj+0]*aa[sj+2][sj+1]-aa[sj+1][sj+1]*aa[sj+2][sj+0]);
11375  FTYPE idet = 1.0/det;
11376  ia[sj+0][sj+0] = (aa[sj+1][sj+1]*aa[sj+2][sj+2]-aa[sj+2][sj+1]*aa[sj+1][sj+2])*idet;
11377  ia[sj+1][sj+0] = -(aa[sj+0][sj+1]*aa[sj+2][sj+2]-aa[sj+0][sj+2]*aa[sj+2][sj+1])*idet;
11378  ia[sj+2][sj+0] = (aa[sj+0][sj+1]*aa[sj+1][sj+2]-aa[sj+0][sj+2]*aa[sj+1][sj+1])*idet;
11379  ia[sj+0][sj+1] = -(aa[sj+1][sj+0]*aa[sj+2][sj+2]-aa[sj+1][sj+2]*aa[sj+2][sj+0])*idet;
11380  ia[sj+1][sj+1] = (aa[sj+0][sj+0]*aa[sj+2][sj+2]-aa[sj+0][sj+2]*aa[sj+2][sj+0])*idet;
11381  ia[sj+2][sj+1] = -(aa[sj+0][sj+0]*aa[sj+1][sj+2]-aa[sj+1][sj+0]*aa[sj+0][sj+2])*idet;
11382  ia[sj+0][sj+2] = (aa[sj+1][sj+0]*aa[sj+2][sj+1]-aa[sj+2][sj+0]*aa[sj+1][sj+1])*idet;
11383  ia[sj+1][sj+2] = -(aa[sj+0][sj+0]*aa[sj+2][sj+1]-aa[sj+2][sj+0]*aa[sj+0][sj+1])*idet;
11384  ia[sj+2][sj+2] = (aa[sj+0][sj+0]*aa[sj+1][sj+1]-aa[sj+1][sj+0]*aa[sj+0][sj+1])*idet;
11385 
11386  if(!isfinite(det) || !isfinite(idet)){
11387  if(debugfail>=2) dualfprintf(fail_file,"inverse_33matrix got singular det=%g idet=%g\n",det,idet);
11388  return(1); // indicates failure
11389  // myexit(13235);
11390  }
11391 
11392  return(0);
11393 }
11394 
11395 
11401 static int inverse_11matrix(int sj, int ej, FTYPE aa[][NDIM], FTYPE ia[][NDIM])
11402 {
11403  // trivial inversion, and can't fail unless divide by zero
11404  // sj==ru->endjac
11405 
11406  ia[sj][sj]=1.0/aa[sj][sj];
11407 
11408  if(!isfinite(ia[sj][sj])){
11409  if(debugfail>=2) dualfprintf(fail_file,"inverse 1x1 zero or nan\n",aa[sj][sj]);
11410  return(1); // indicates failure
11411  // myexit(13235);
11412  }
11413  return(0);
11414 
11415 }
11416 
11417 
11418 
11419 
11420 
11432 int prad_fforlab(int *whichvel, int *whichcoord, int whichdir, int i, int j, int k, int loc, struct of_geom *ptrgeom, FTYPE *pradffortho, FTYPE *pin, FTYPE *pout)
11433 {
11434 
11435  if(whichdir==FF2LAB) prad_fftolab(whichvel, whichcoord, i, j, k, loc, ptrgeom, pradffortho, pin, pout);
11436  else if(whichdir==LAB2FF) prad_labtoff(whichvel, whichcoord, i, j, k, loc, ptrgeom, pradffortho, pin, pout);
11437  else{
11438  dualfprintf(fail_file,"prad_fforlab() not yet setup for whichdir=%d.",whichdir);
11439  myexit(652526624);
11440  }
11441 
11442  return(0);
11443 
11444 }
11445 
11448 int prad_labtoff(int *whichvel, int *whichcoord, int i, int j, int k, int loc, struct of_geom *ptrgeom, FTYPE *pradffortho, FTYPE *pin, FTYPE *pout)
11449 {
11450  int jj;
11451 
11452  // DLOOPA(jj) dualfprintf(fail_file,"ijk=%d %d %d : jj=%d pin=%g\n",i,j,k,jj,pin[PRAD0+jj]);
11453 
11454  // assume ptrgeom is PRIMECOORDS lab-frame geometry
11455  struct of_geom geomdontuse;
11456  if(ptrgeom==NULL){
11457  ptrgeom=&geomdontuse;
11458  get_geometry(i, j, k, loc, ptrgeom);
11459  }
11460 
11461 
11462 
11463  // get state
11464  struct of_state q;
11465  get_state(pin,ptrgeom,&q);
11466 
11467  // DLOOPA(jj) dualfprintf(fail_file,"ijk=%d %d %d : jj=%d uradcon=%g uradcov=%g\n",i,j,k,jj,q.uradcon[jj],q.uradcov[jj]);
11468 
11469 
11470  // get lab-frame R^\mu_\nu
11471  FTYPE Rijlab[NDIM][NDIM];
11472  mhdfull_calc_rad(pin, ptrgeom, &q, Rijlab);
11473 
11474 #if(0) // STAY AS ZERO
11475 
11476  // get U=R^t_\mu [harm type]
11477  FTYPE U[NDIM];
11478  DLOOPA(jj) U[jj]=Rijlab[TT][jj];
11479 
11480  // DLOOPA(jj) dualfprintf(fail_file,"ijk=%d %d %d : jj=%d U=%g ucon=%g ucov=%g\n",i,j,k,jj,U[jj],q.ucon[jj],q.ucov[jj]);
11481 
11482  // transform lab-frame R^t_\nu [harm type] to fluid-frame version
11483  FTYPE Uff[NDIM];
11485 
11486  // DLOOPA(jj) dualfprintf(fail_file,"ijk=%d %d %d : jj=%d Uff=%g alpha=%g\n",i,j,k,jj,Uff[jj],ptrgeom->alphalapse);
11487 
11488  // 00 01 02 03 11 12 13 22 23 33
11489  // FTYPE etamink[SYMMATRIXNDIM]={-1 ,0 ,0 ,0, 1 ,0 ,0 ,1 ,0 ,1};
11490  Uff[TT]*=1.0; // if original was R_\mu get R^\mu in fluid frame orthonormal basis
11491 
11492  DLOOPA(jj) pradffortho[PRAD0+jj] = Uff[jj];
11493 
11494 #else
11495 
11496  // int kk;
11497  // DLOOP(jj,kk) dualfprintf(fail_file,"gn%d%d=%21.15g\n",jj+1,kk+1,ptrgeom->gcon[GIND(jj,kk)]);
11498  // DLOOP(jj,kk) dualfprintf(fail_file,"gv%d%d=%21.15g\n",jj+1,kk+1,ptrgeom->gcov[GIND(jj,kk)]);
11499 
11500  indices_2122(Rijlab,Rijlab,ptrgeom);
11501 
11502  // Need to use full Rijlab since can be mixing between components in general
11503  // transform and boost (ultimately converts pin -> Rijlab-> pradffortho -> Rijff effectively)
11504  int tconcovtypeA=TYPEUCON;
11505  int tconcovtypeB=TYPEUCON;
11506  int primcoord=1;// 1 so that will use optimal way to get tetrads
11507  FTYPE Rijff[NDIM][NDIM];
11508  tensor_lab2orthofluidorback(primcoord, LAB2FF, ptrgeom, TYPEUCON, q.ucon, tconcovtypeA, tconcovtypeB, Rijlab, Rijff);
11509 
11510  // DLOOPA(jj) dualfprintf(fail_file,"ijk=%d %d %d : jj=%d Rijff[TT]=%g alpha=%g\n",i,j,k,jj,Rijff[TT][jj],ptrgeom->alphalapse);
11511 
11512  // get in pradffortho form
11513  DLOOPA(jj) pradffortho[PRAD0+jj] = Rijff[TT][jj];
11514 
11515 #endif
11516 
11517  // just copy pout
11518  int pliter,pl;
11519  PLOOP(pliter,pl) pout[pl]=pin[pl];
11520 
11521  return(0);
11522 }
11523 
11526 int prad_fftolab(int *whichvel, int *whichcoord, int i, int j, int k, int loc, struct of_geom *ptrgeom, FTYPE *pradffortho, FTYPE *pin, FTYPE *pout)
11527 {
11528  FTYPE Rijff[NDIM][NDIM],Rijlab[NDIM][NDIM],U[NPR]={0};
11529  int pliter,pl;
11530  int primcoord;
11531  int jj,kk;
11532  struct of_geom geomtousedontuse;
11533  struct of_geom *ptrgeomtouse=&geomtousedontuse;
11534 
11535 
11536  if(ptrgeom==NULL){
11537  if(*whichcoord!=PRIMECOORDS){
11538  // get metric grid geometry for these ICs
11539  int getprim=0;
11540  gset_genloc(getprim,*whichcoord,i,j,k,loc,ptrgeomtouse);
11541  }
11542  else{
11543  get_geometry(i, j, k, loc, ptrgeomtouse);
11544  }
11545  }
11546  else{
11547  // then assumes ptrgeom is in *whichcoord coordinates
11548  ptrgeomtouse=ptrgeom;
11549  }
11550 
11551 
11552  // set primitive that can use as pre-existing fluid velocity if need to use for reduction
11553  // also use pout instead of pin so preserves pin no matter what (unless user set pin=pout)
11554  PLOOP(pliter,pl) pout[pl]=pin[pl];
11555 
11556 
11557  // radiative stress tensor in the fluid frame orthonormal basis
11558  // assuming input pradffortho for radiation is in fluid frame orthonormal basis, but in "primitive" format so using pradffortho[PRAD0-PRAD3]
11559  // gets R^{ij} in fluid frame orthonormal basis from primitive quantities in fluid frame orthonormal basis
11560  calc_Rij_ff(pradffortho,Rijff);
11561 
11562  // PLOOPRADONLY(pl) dualfprintf(fail_file,"pl=%d pout=%g\n",pl,pout[pl]);
11563  // DLOOP(jj,kk) dualfprintf(fail_file,"jj=%d kk=%d Rijff=%g\n",jj,kk,Rijff[jj][kk]);
11564  // DLOOP(jj,kk) dualfprintf(fail_file,"gn%d%d=%21.15g\n",jj+1,kk+1,ptrgeomtouse->gcon[GIND(jj,kk)]);
11565  // DLOOP(jj,kk) dualfprintf(fail_file,"gv%d%d=%21.15g\n",jj+1,kk+1,ptrgeomtouse->gcov[GIND(jj,kk)]);
11566 
11567 
11568  // get ucon (assumed primitive velocity in ptrgeomtouse coordinates)
11569  FTYPE ucon[NDIM],others[NUMOTHERSTATERESULTS];
11570  ucon_calc_whichvel(*whichvel,pout,ptrgeomtouse,ucon,others);
11571 
11572  // DLOOPA(jj) dualfprintf(fail_file,"jj=%d ucon=%g\n",jj,ucon[jj]);
11573 
11574 
11575  // also convert whichvel ucon to VELREL4 primitive velocity for use by u2p_rad() and as needed for consistent final output from this function and as possible backup value
11576  if(*whichvel!=VELREL4) ucon2pr(VELREL4,ucon,ptrgeomtouse,pout);
11577 
11578  // SLOOPA(jj) dualfprintf(fail_file,"jj=%d u4rel=%g\n",jj,pout[UU+jj]);
11579 
11580  // transform and boost (ultimately converts pradffortho -> Rijff -> Rijlab -> U)
11581  int tconcovtypeA=TYPEUCON;
11582  int tconcovtypeB=TYPEUCON;
11583  if(*whichcoord==PRIMECOORDS) primcoord=1;
11584  else primcoord=0;
11585  tensor_lab2orthofluidorback(primcoord, FF2LAB, ptrgeomtouse, TYPEUCON, ucon, tconcovtypeA, tconcovtypeB, Rijff, Rijlab);
11586 
11587  // DLOOP(jj,kk) dualfprintf(fail_file,"jj=%d kk=%d Rijlab=%g\n",jj,kk,Rijlab[jj][kk]);
11588 
11589  //R^munu -> R^mu_nu so in standard form to extract conserved quantity R^t_\nu
11590  indices_2221(Rijlab,Rijlab,ptrgeomtouse);
11591 
11592  // DLOOP(jj,kk) dualfprintf(fail_file,"jj=%d kk=%d Ridownjlab=%g\n",jj,kk,Rijlab[jj][kk]);
11593 
11594  // Store radiation conserved quantity from R^t_\nu . u2p_rad() below only uses radiation U's.
11595 #if(0) // STAY ZERO NOW
11596  // for true lab to fake-harm lab, end up dividing by alpha (see vector_harm2orthofluidorback() in tetrad.c)
11597  FTYPE alpha=ptrgeomtouse->alphalapse;
11598  U[URAD0]=Rijlab[TT][TT]/alpha;
11599  U[URAD1]=Rijlab[TT][RR]/alpha;
11600  U[URAD2]=Rijlab[TT][TH]/alpha;
11601  U[URAD3]=Rijlab[TT][PH]/alpha;
11602 #else
11603  U[URAD0]=Rijlab[TT][TT];
11604  U[URAD1]=Rijlab[TT][RR];
11605  U[URAD2]=Rijlab[TT][TH];
11606  U[URAD3]=Rijlab[TT][PH];
11607 #endif
11608 
11609  // DLOOPA(jj) dualfprintf(fail_file,"jj=%d URAD=%g\n",jj,U[URAD0+jj]);
11610 
11611 
11612 
11613 
11614  PFTYPE lpflag=UTOPRIMNOFAIL,lpflagrad=UTOPRIMRADNOFAIL;
11615  int showmessages=1; // LEAVE on (not normal debugging)
11616  int allowlocalfailurefixandnoreport=1;
11617  // NOTEMARK: lpflag=UTOPRIMNOFAIL means accept input pout for velocity to maybe be used in local reductions to fluid frame.
11618  // u2p_rad() only uses U[URAD0-URAD3]
11619  // generally u2p_rad() could use all of pout[] except only assigns pout[PRAD0-PRAD3] and doesn't use that for anything except as "static" solution (i.e. uses pin effectively)
11620  u2p_rad(showmessages, allowlocalfailurefixandnoreport, GAMMAMAXRAD, CAPTYPEBASIC, U, pout, ptrgeomtouse, &lpflag, &lpflagrad);
11621 
11622  // DLOOPA(jj) dualfprintf(fail_file,"u2p_rad: jj=%d pout=%g\n",jj,pout[PRAD0+jj]);
11623 
11624 
11625 
11626  // get back to whichvel
11627  FTYPE uconback[NDIM],othersback[NUMOTHERSTATERESULTS];
11628  // for fluid
11629  ucon_calc_whichvel(VELREL4,pout,ptrgeomtouse,uconback,othersback);
11630  ucon2pr(*whichvel,uconback,ptrgeomtouse,pout);
11631  // KORALTODO: for radiation (always returned as VELREL4 so far).
11632  ucon_calc_whichvel(VELREL4,&pout[URAD1-U1],ptrgeomtouse,uconback,othersback);
11633  ucon2pr(*whichvel,uconback,ptrgeomtouse,&pout[URAD1-U1]);
11634 
11635 
11636 
11637  // DEBUG:
11638  if(lpflag!=UTOPRIMNOFAIL || lpflagrad!=UTOPRIMRADNOFAIL){ // DEBUG with 1||
11639  // allows fixups to be applied, such as gamma radiation limiting
11640  if(lpflag>UTOPRIMNOFAIL || lpflagrad>UTOPRIMRADNOFAIL){ // DEBUG with 1||
11641  if(debugfail>=2){
11642  dualfprintf(fail_file,"Failed to invert during prad_fftolab(). Assuming fixups won't be applied: %d %d\n",lpflag,lpflagrad);
11643  dualfprintf(fail_file,"ijk=%d %d %d : %d\n",ptrgeomtouse->i,ptrgeomtouse->j,ptrgeomtouse->k,ptrgeomtouse->p);
11644  PLOOP(pliter,pl) dualfprintf(fail_file,"pl=%d pin=%g U=%g\n",pl,pin[pl],U[pl]);
11645  DLOOPA(jj) dualfprintf(fail_file,"jj=%d ucon=%g\n",jj,ucon[jj]);
11646  DLOOP(jj,kk) dualfprintf(fail_file,"jj=%d kk=%d Rijff=%g Rijlab=%g\n",jj,kk,Rijff[jj][kk],Rijlab[jj][kk]);
11647  DLOOP(jj,kk) dualfprintf(fail_file,"jj=%d kk=%d gcov=%g gcon=%g\n",jj,kk,ptrgeomtouse->gcov[GIND(jj,kk)],ptrgeomtouse->gcon[GIND(jj,kk)]);
11648  PLOOP(pliter,pl) dualfprintf(fail_file,"pl=%d pout=%g\n",pl,pout[pl]);
11649  }
11650  if(lpflag==UTOPRIMNOFAIL && (lpflagrad==UTOPRIMRADFAILERFNEG || lpflagrad==UTOPRIMRADFAILGAMMAHIGH) ){
11651  // then probably not really failure, just have high ERADLIMIT for other reasons.
11652  }
11653  else{
11654  myexit(189235);
11655  // KORALTODO: Check whether really succeeded? Need to call fixups? Probably, but need per-cell fixup. Hard to do if other cells not even set yet as in ICs. Should probably include fixup process during initbase.c stuff.
11656  }
11657  }
11658  else{
11659  if(debugfail>=2){
11660  dualfprintf(fail_file,"Fixups applied during invert during prad_fftolab(): %d %d\n",lpflag,lpflagrad);
11661  dualfprintf(fail_file,"ijk=%d %d %d : %d\n",ptrgeomtouse->i,ptrgeomtouse->j,ptrgeomtouse->k,ptrgeomtouse->p);
11662  }
11663  }
11664  }
11665 
11666 
11667 
11668  return 0;
11669 }
11670 
11671 
11672 
11673 
11674 
11675 
11676 
11677 
11678 
11679 
11680 
11681 
11684 int primefluid_EVrad_to_primeall(int *whichvel, int *whichcoord, struct of_geom *ptrgeom, FTYPE *pin, FTYPE *pout)
11685 {
11686  int pliter,pl;
11687  int i=ptrgeom->i;
11688  int j=ptrgeom->j;
11689  int k=ptrgeom->k;
11690  int loc=ptrgeom->p;
11691 
11692  // copy over
11693  PLOOP(pliter,pl) pout[pl]=pin[pl];
11694 
11695  // get metric grid geometry for these ICs
11696  int getprim=0;
11697  struct of_geom geomrealdontuse;
11698  struct of_geom *ptrgeomreal=&geomrealdontuse;
11699  gset_genloc(getprim,*whichcoord,i,j,k,loc,ptrgeomreal);
11700 
11701  FTYPE uradcon[NDIM],othersrad[NUMOTHERSTATERESULTS];
11702  ucon_calc_whichvel(*whichvel,&pout[URAD1-U1],ptrgeomreal,uradcon,othersrad);
11703 
11704  // now convert velocity so in PRIMECOORDS assuming whichcoord=MCOORD
11705  mettometp_genloc(i,j,k,loc,uradcon);
11706 
11707  if(*whichcoord!=MCOORD){
11708  dualfprintf(fail_file,"primefluid_EVrad_to_primeall() needs whichcoord (%d) to be MCOORD (%d)\n",whichcoord,MCOORD);
11709  myexit(87345246);
11710  }
11711 
11712  // assumed already inputted PRIMECOORDS WHICHVEL for fluid velocity, so no conversion for the fluid velocity
11713 
11714  // now go from ucon[PRIMECOORDS] -> primitive[PRIMECOORDS] for radiation velocity and get WHICHVEL version
11715  ucon2pr(WHICHVEL,uradcon,ptrgeom,&pout[URAD1-U1]);
11716 
11717  // now all PRIMECOORDS WHICHVEL type assuming ptrgeom inputted PRIMECOORDS version as expected
11718  *whichvel=WHICHVEL;
11719  *whichcoord=PRIMECOORDS;
11720 
11721  return(0);
11722 }
11723 
11724 
11729 int whichfluid_ffrad_to_primeall(int *whichvel, int *whichcoordfluid, int *whichcoordrad, struct of_geom *ptrgeomprimecoords, FTYPE *pradffortho, FTYPE *pin, FTYPE *pout)
11730 {
11731  int pliter,pl;
11732  int i=ptrgeomprimecoords->i;
11733  int j=ptrgeomprimecoords->j;
11734  int k=ptrgeomprimecoords->k;
11735  int loc=ptrgeomprimecoords->p;
11736 
11737 
11738  // PLOOP(pliter,pl) dualfprintf(fail_file,"ijk=%d %d %d pl=%d pin0=%g pout0=%g\n",i,j,k,pl,pin[pl],pout[pl]);
11739 
11740  // prad_fforlab() should only use radiation primitives, but copy all primitives so can form ucon for transformation
11741  PLOOP(pliter,pl) pout[pl]=pin[pl];
11742 
11743  // 4 cases:
11744  // rad fluid
11745  // PRIME PRIME
11746  // PRIME other
11747  // other PRIME
11748  // other other
11749 
11750  // get real geometry if needed
11751  struct of_geom geomrealraddontuse;
11752  struct of_geom *ptrgeomrealrad=&geomrealraddontuse;
11753  struct of_geom geomrealfluiddontuse;
11754  struct of_geom *ptrgeomrealfluid=&geomrealfluiddontuse;
11755  if(*whichcoordrad!=PRIMECOORDS){
11756  int getprim=0;
11757  gset_genloc(getprim,*whichcoordrad,i,j,k,loc,ptrgeomrealrad);
11758  }
11759  else ptrgeomrealrad=ptrgeomprimecoords;
11760  if(*whichcoordfluid!=PRIMECOORDS){
11761  int getprim=0;
11762  gset_genloc(getprim,*whichcoordfluid,i,j,k,loc,ptrgeomrealfluid);
11763  }
11764  else ptrgeomrealfluid=ptrgeomprimecoords;
11765 
11766 
11767 
11768  // make whichcoord for fluid same as for rad before continuing (make fluid same as radiation by only changing fluid whichcoord)
11769  if(*whichcoordfluid!=*whichcoordrad){
11770  FTYPE ucon[NDIM];
11771  FTYPE others[NUMOTHERSTATERESULTS];
11772 
11773  // pr->ucon for fluid
11774  if (pr2ucon(*whichvel,pout, ptrgeomrealfluid, ucon) >= 1) FAILSTATEMENT("bounds.koral.c:bl2met2metp2v_genloc() for radiation", "pr2ucon()", 2);
11775 
11776  if(*whichcoordfluid==PRIMECOORDS){ // then radiation is not PRIMECOORDS, so go to radiation coords
11777  metptomet_genloc(i,j,k,loc,ucon); // now ucon is in MCOORD
11778  // convert MCOORD->whichcoordrad
11779  coordtrans(MCOORD,*whichcoordrad,i,j,k,loc,ucon);
11780  }
11781  else if(*whichcoordrad==PRIMECOORDS){ // then go to PRIMECOORDS for fluid
11782  // convert whichcoordfluid->MCOORD
11783  coordtrans(*whichcoordfluid,MCOORD,i,j,k,loc,ucon);
11784  mettometp_genloc(i,j,k,loc,ucon); // now ucon is in PRIMECOORDS
11785  }
11786  else{ // then neither is PRIMECOORDS, so just transform and skip mettometp() or metptomet()
11787  // convert whichcoordfluid->whichcoordrad
11788  coordtrans(*whichcoordfluid,*whichcoordrad,i,j,k,loc,ucon);
11789  }
11790 
11791  // get whichvel primitive
11792  ucon2pr(*whichvel,ucon,ptrgeomrealrad,pout);
11793 
11794  // changed fluid to have same whichcoord as radiation (set by radiation), so set that
11795  *whichcoordfluid=*whichcoordrad;
11796 
11797  }
11798  else{
11799  // otherwise, whichcoord same for fluid and radiation, so can continue
11800  }
11801 
11802 
11803  // PLOOP(pliter,pl) dualfprintf(fail_file,"PRE: ijk=%d %d %d pl=%d pout=%g\n",i,j,k,pl,pout[pl]);
11804 
11805 
11806 
11807  // get WHICHVEL primitives (still will be in whichcoord coordinates)
11808  // whichvel here is for fluid velocity (prad_fforlab() converts velocity to WHICHVEL for consistency with only currently allowed output of radiation velocity)
11809  // pradffortho assumed as in orthonormal fluid frame, but coordinates of whichcoordrad
11810  int whichframedir=FF2LAB; // fluid frame orthonormal to lab-frame
11811  prad_fforlab(whichvel, whichcoordrad, whichframedir, i, j, k, loc, ptrgeomrealrad, pradffortho, pout, pout);
11812 
11813  // output from prad_fforlab() is always WHICHVEL for both fluid and radiation primitives
11814  // changed whichvel's, so report that back if needed
11815  // *whichvel=WHICHVEL;
11816  // above change of whichvel no longer true (and anyways, whichvel was changed in prad_fforlab() directly)
11817 
11818  // PLOOP(pliter,pl) dualfprintf(fail_file,"POST: ijk=%d %d %d pl=%d pout=%g\n",i,j,k,pl,pout[pl]);
11819 
11820 
11821  // output from prad_fforlab() not yet necessarily PRIMECOORDS.
11822  if(*whichcoordrad==MCOORD){
11823  // Get all primitives in WHICHVEL/PRIMECOORDS (no conversion for WHICHVEL since prad_fforlab() already put quantities in WHICHVEL due to u2p_rad() only setup for WHICHVEL)
11824  if (bl2met2metp2v_genloc(*whichvel, *whichcoordrad, pout, i,j,k,loc) >= 1){
11825  FAILSTATEMENT("bounds.koral.c:bound_radatmbeaminflow()", "bl2ks2ksp2v()", 1);
11826  }
11827  }
11828 
11829  // changed coordinates to PRIMECOORDS, so set that as the case
11830  *whichcoordfluid=*whichcoordrad=PRIMECOORDS;
11831 
11832  return(0);
11833 
11834 }
11835 
11836 
11837 /*****************************************************************/
11838 /*****************************************************************/
11839 /*****************************************************************/
11841 int indices_2221(FTYPE T1[][NDIM],FTYPE T2[][NDIM], struct of_geom *ptrgeom)
11842 {
11843  int i,j,k;
11844  FTYPE Tt[NDIM][NDIM];
11845 
11846  for(i=0;i<NDIM;i++)
11847  {
11848  for(j=0;j<NDIM;j++)
11849  {
11850  Tt[i][j]=0.;
11851  for(k=0;k<NDIM;k++)
11852  {
11853  Tt[i][j]+=T1[i][k]*ptrgeom->gcov[GIND(k,j)];
11854  }
11855  }
11856  }
11857 
11858  for(i=0;i<NDIM;i++)
11859  {
11860  for(j=0;j<NDIM;j++)
11861  {
11862  T2[i][j]=Tt[i][j];
11863  }
11864  }
11865 
11866  return 0;
11867 }
11868 
11869 /*****************************************************************/
11870 /*****************************************************************/
11871 /*****************************************************************/
11873 int indices_2212(FTYPE T1[][NDIM],FTYPE T2[][NDIM], struct of_geom *ptrgeom)
11874 {
11875  int i,j,k;
11876  FTYPE Tt[NDIM][NDIM];
11877 
11878  for(i=0;i<NDIM;i++)
11879  {
11880  for(j=0;j<NDIM;j++)
11881  {
11882  Tt[i][j]=0.;
11883  for(k=0;k<NDIM;k++)
11884  {
11885  Tt[i][j]+=T1[k][j]*ptrgeom->gcov[GIND(k,i)];
11886  }
11887  }
11888  }
11889 
11890  for(i=0;i<NDIM;i++)
11891  {
11892  for(j=0;j<NDIM;j++)
11893  {
11894  T2[i][j]=Tt[i][j];
11895  }
11896  }
11897 
11898  return 0;
11899 }
11900 
11902 int indices_2122(FTYPE T1[][NDIM],FTYPE T2[][NDIM], struct of_geom *ptrgeom)
11903 {
11904  int i,j,k;
11905  FTYPE Tt[NDIM][NDIM];
11906 
11907  for(i=0;i<NDIM;i++)
11908  {
11909  for(j=0;j<NDIM;j++)
11910  {
11911  Tt[i][j]=0.;
11912  for(k=0;k<NDIM;k++)
11913  {
11914  Tt[i][j]+=T1[i][k]*ptrgeom->gcon[GIND(k,j)];
11915  }
11916  }
11917  }
11918 
11919  for(i=0;i<NDIM;i++)
11920  {
11921  for(j=0;j<NDIM;j++)
11922  {
11923  T2[i][j]=Tt[i][j];
11924  }
11925  }
11926 
11927  return 0;
11928 }
11929 
11930 /*****************************************************************/
11931 /*****************************************************************/
11932 /*****************************************************************/
11934 int indices_21(FTYPE A1[NDIM],FTYPE A2[NDIM],struct of_geom *ptrgeom)
11935 {
11936  int i,j,k;
11937  FTYPE At[NDIM];
11938 
11939  for(i=0;i<NDIM;i++)
11940  {
11941  At[i]=0.;
11942  for(k=0;k<NDIM;k++)
11943  {
11944  At[i]+=A1[k]*ptrgeom->gcov[GIND(i,k)];
11945  }
11946  }
11947 
11948  for(i=0;i<NDIM;i++)
11949  {
11950  A2[i]=At[i];
11951  }
11952 
11953  return 0;
11954 }
11955 
11956 /*****************************************************************/
11957 /*****************************************************************/
11958 /*****************************************************************/
11960 int indices_12(FTYPE A1[NDIM],FTYPE A2[NDIM],struct of_geom *ptrgeom)
11961 {
11962  int i,j,k;
11963  FTYPE At[NDIM];
11964 
11965  for(i=0;i<NDIM;i++)
11966  {
11967  At[i]=0.;
11968  for(k=0;k<NDIM;k++)
11969  {
11970  At[i]+=A1[k]*ptrgeom->gcon[GIND(i,k)];
11971  }
11972  }
11973 
11974  for(i=0;i<NDIM;i++)
11975  {
11976  A2[i]=At[i];
11977  }
11978 
11979  return 0;
11980 }
11981 
11982 
11983 
11984 int u2p_rad(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, int whichcap, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad)
11985 {
11986  int u2p_rad_new(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, int whichcap, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad);
11987  int u2p_rad_orig(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad);
11988  int u2p_rad_new_pre(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad);
11989  int toreturn;
11990  int pliter,pl;
11991  FTYPE prorig[NPR];
11992 
11993 
11995  //
11996  // CHECK if should abort inversion attempt if already dropped-out value in uu
11997  //
11999 #if(0)
12000  // put in a catch for when inputted uu[URAD0] has dropped-out already and don't try to invert.
12001  if(fabs(uu[URAD0]<=2.0*10.0*ERADLIMIT)){ // often 10*ERADLIMIT is used to set as above ERADLIMIT, so here a higher catch is 2*10*ERADLIMIT
12002  // force to be reasonable
12003  // currently always return WHICHVEL=VELREL4, so just set to floor values
12004  pin[URAD0]=ERADLIMIT;
12005  int jj;
12006  SLOOPA(jj) pin[URAD1+jj-1] = 0.0;
12007  return(0);
12008  }
12009 #endif
12010 
12011 
12013  //
12014  // NORMAL ATTEMPT where we compute inversion
12015  //
12017 
12018 
12019  // store orig
12020  PLOOP(pliter,pl) prorig[pl] = pin[pl];
12021 
12022 #if(WHICHU2PRAD==0)
12023  toreturn=u2p_rad_orig(showmessages, allowlocalfailurefixandnoreport, gammamaxrad, uu, pin, ptrgeom,lpflag, lpflagrad);
12024 #else
12025  //toreturn=u2p_rad_new_pre(showmessages, allowlocalfailurefixandnoreport, gammamaxrad, uu, pin, ptrgeom,lpflag, lpflagrad);
12026  toreturn=u2p_rad_new(showmessages, allowlocalfailurefixandnoreport, gammamaxrad, whichcap, uu, pin, ptrgeom,lpflag, lpflagrad);
12027 #endif
12028 
12029 
12030  // scalar inversions
12031 
12032 
12033 
12034 
12035 
12036 #if(PRODUCTION==0)
12037  int caughtnan=0;
12038  if(!finite(pin[URAD0]) || !finite(pin[URAD1]) || !finite(pin[URAD2]) || !finite(pin[URAD3])){
12039  // __WORKINGONIT__: Shouldn't happen, but does on Kraken
12040  caughtnan=1;
12041  }
12042 
12043  if(caughtnan){
12044 
12045  if(debugfail>=2){
12046  dualfprintf(fail_file,"u2p_rad() generated nan result: %d %d %g %d\n",showmessages, allowlocalfailurefixandnoreport, gammamaxrad, whichcap);
12047  PLOOP(pliter,pl) dualfprintf(fail_file,"u2p_rad: pl=%d prorig=%21.15g uu=%21.15g pin=%21.15g\n",pl,prorig[pl],uu[pl],pin[pl]);
12048  }
12049 
12050 
12051  if(0){ // __WORKINGONIT__: if doing iterations, need to let fail with nan so aborts and stops trying right away. Otherwise huge waste.
12052  // force to be reasonable
12053  // currently always return WHICHVEL=VELREL4, so just set to floor values
12054  pin[URAD0]=ERADLIMIT;
12055  int jj;
12056  SLOOPA(jj) pin[URAD1+jj-1] = 0.0;
12057  }
12058 
12059  }
12060 #endif
12061 
12062 
12063 
12064 
12065 
12066  return(toreturn);
12067 }
12068 
12069 
12070 
12076 int u2p_rad_new_pre(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad)
12077 {
12078  static long long int numyvarneg,numyvarbig,numErneg,nummod;
12079  int recomputegamma=0;
12080 
12081 #if(WHICHVEL!=VELREL4)
12082  dualfprintf(fail_file,"u2p_rad() only setup for relative 4-velocity, currently.\n");
12083  myexit(137432636);
12084 #endif
12085 
12086 
12087  // copy over pin so pin isn't modified until end
12088  int pliter,pl;
12089  FTYPE pp[NPR];
12090  PLOOP(pliter,pl) pp[pl]=pin[pl];
12091 
12093  //
12094  // Prepare inversion from U->p for radiation assuming M1 closure
12095  //
12097 
12098  *lpflagrad=UTOPRIMRADNOFAIL;
12099 
12100  FTYPE Er,Utildesq,Utildecon[NDIM];
12101  compute_ZAMORAD(uu, ptrgeom, &Er, &Utildesq, Utildecon);
12102 
12103 
12104 
12105  FTYPE Ersq,yvar;
12106  int didmod=0;
12107 
12108  // if(1||gammamaxrad>0.9*GAMMAMAXRADIMPLICITSOLVER || Er>=ERADLIMIT){ // then good solution. Avoid caps during implicit solver to allow progress on solution in smooth way.
12109  if(Er>=ERADLIMIT){ // then good solution. Avoid caps during implicit solver to allow progress on solution in smooth way.
12110  // Er^2
12111  Ersq=Er*Er;
12112  // y
12113  yvar = Utildesq / (ERADLIMIT*ERADLIMIT + Ersq); // ERADLIMIT*ERADLIMIT better be machine representable in case Ersq is not.
12114  }
12115  else{// then bad solution
12116  // dualfprintf(fail_file,"Er=%26.20g<ERADLIMIT=%26.20g yvar=%26.20g Utildesq=%26.20g Ersq=%26.20g\n",Er,ERADLIMIT,yvar,Utildesq,Ersq);
12117  Ersq=ERADLIMIT*ERADLIMIT;
12118  yvar = 0.0;
12119  didmod=1;
12120  numErneg++;
12121  }
12122 
12123  // dualfprintf(fail_file,"Er=%g Utildesq=%g\n",Er,Utildesq);
12124 
12125  // \gamma_{\rm rad}^2 : only 1 root
12126  FTYPE gammasq,gamma;
12127  FTYPE gammamax=gammamaxrad;
12128  FTYPE gammamaxsq=gammamax*gammamax;
12129  FTYPE ylimit = 16.0*gammamaxsq*(gammamaxsq-1.0)/((4.0*gammamaxsq-1.0)*(4.0*gammamaxsq-1.0));
12130  if(yvar<0.0){
12131  // dualfprintf(fail_file,"Er=%26.20g yvar=%26.20g<0.0 Utildesq=%26.20g Ersq=%26.20g\n",Er,yvar,Utildesq,Ersq);
12132  yvar=0.0;
12133  gammasq = 1.0;
12134  gamma = 1.0;
12135  didmod=1;
12136  numyvarneg++;
12137  }
12138  else if(yvar>ylimit){ // beyond gamma limit, then rescale gamma
12139  yvar=ylimit;
12140  gammasq = gammamaxsq;
12141  gamma = gammamax;
12142  didmod=1; *lpflagrad=UTOPRIMRADFAILCASE2A; // used to detec if modified primitives to not be consistent with inputted uu
12143  numyvarbig++;
12144  // dualfprintf(fail_file,"yvar=%g>%g Ersq=%g gamma=%g\n",yvar,ylimit,Ersq,gamma);
12145  }
12146  else{ // normal solution
12147  gammasq = (2.0 - yvar + sqrt(4.0-3.0*yvar))/ (4.0*(1.0-yvar));
12148  gamma=sqrt(gammasq);
12149  // dualfprintf(fail_file,"yvar=%g Ersq=%g gamma=%g\n",yvar,Ersq,gamma);
12150  }
12151 
12152  FTYPE Erf;
12153  FTYPE urfconrel[NDIM]={0.0};
12154  int jj;
12155  // if(1||gammamaxrad>0.9*GAMMAMAXRADIMPLICITSOLVER || Er>=ERADLIMIT){ // then good solution. Avoid caps during implicit solver to allow progress on solution in smooth way.
12156  if(Er>=ERADLIMIT){ // then good solution. Avoid caps during implicit solver to allow progress on solution in smooth way.
12157  // now obtain primitives
12158  FTYPE pr = Er/(4.0*gammasq-1.0);
12159  // radiation frame energy density
12160  // Erf = pr/(4.0/3.0-1.0);
12161  Erf = 3.0*pr;
12162 
12163  // radiation frame relativity 4-velocity
12164  SLOOPA(jj) urfconrel[jj] = (Utildecon[jj]/(4.0*pr*gamma));
12165  recomputegamma=1;
12166  }
12167  else{
12168  Erf = ERADLIMIT;
12169  gamma=1.0;
12170  // radiation frame relativity 4-velocity
12171  SLOOPA(jj) urfconrel[jj] = 0.0;
12172  recomputegamma=1;
12173  didmod=1; *lpflagrad=UTOPRIMRADFAILERFNEG; // used to detect if modified primitives to not be consistent with inputted uu
12174  }
12175 
12176 
12178  //
12179  //new primitives (only uses urfcon[1-3])
12180  //
12182  pin[PRAD0]=Erf;
12183  pin[PRAD1]=urfconrel[1];
12184  pin[PRAD2]=urfconrel[2];
12185  pin[PRAD3]=urfconrel[3];
12186 
12187  // dualfprintf(fail_file,"didmod=%d\n",didmod);
12188 
12189  // make sure E_r no larger than starting value
12190  if(didmod==1){
12191  nummod++;
12192 
12193 
12194  // First, ensure \gamma correct
12195  FTYPE gammanew,qsqnew;
12196  gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammanew,&qsqnew);
12197  // dualfprintf(fail_file,"gamma=%g gammanew=%g\n",gamma,gammanew);
12198 
12199  // rescale, assuming want to be gamma
12200  FTYPE fvar=sqrt((gamma*gamma-1.0)/(gammanew*gammanew-1.0));
12201  if(gammanew>1.0){
12202  SLOOPA(jj) urfconrel[jj] *= fvar;
12203  }
12204  else{
12205  SLOOPA(jj) urfconrel[jj] *= 0.0;
12206  }
12207  recomputegamma=1;
12208 
12209  // dualfprintf(fail_file,"urfconrel=%g %g %g\n",urfconrel[1],urfconrel[2],urfconrel[3]);
12210 
12211 
12212  // new prims
12213  pin[PRAD1]=urfconrel[1];
12214  pin[PRAD2]=urfconrel[2];
12215  pin[PRAD3]=urfconrel[3];
12216 
12217  if(0){ // causes more problems for implicit solver.
12218 
12219  // Second, ensure not creating energy in ZAMO frame
12220  struct of_state q;
12221  get_state_uradconuradcovonly(pin, ptrgeom, &q);
12222  FTYPE Rtnu[NDIM];
12223  mhd_calc_rad( pin, TT, ptrgeom, &q, Rtnu, NULL );
12224  // dualfprintf(fail_file,"Rtnu=%g %g %g %g\n",Rtnu[0],Rtnu[1],Rtnu[2],Rtnu[3]);
12225  FTYPE Ernew,Utildesqnew,Utildeconnew;
12226  compute_ZAMORAD(&Rtnu[0-URAD0], ptrgeom, &Ernew, &Utildesqnew, &Utildeconnew); // out of range warning ok.
12227  Erf = Erf*MIN(1.0,Er/Ernew);
12228  }
12229 
12230  *lpflagrad=UTOPRIMRADFAILCASE2A;
12231 
12232  // could continue iterating, or should find closed form expressions for all this.
12233  // dualfprintf(fail_file,"Ernew=%g Utildesqnew=%g\n",Ernew,Utildesqnew);
12234  }
12235 
12236 
12238  //
12239  // really new primitives (only uses urfcon[1-3])
12240  //
12242  pin[PRAD0]=Erf;
12243  pin[PRAD1]=urfconrel[1];
12244  pin[PRAD2]=urfconrel[2];
12245  pin[PRAD3]=urfconrel[3];
12246 
12247 
12249  //
12250  // INVERT to get Number density of photons in radiation frame
12251  //
12253 #if(EVOLVENRAD&&NRAD>0)
12254  if(*lpflagrad==UTOPRIMRADNOFAIL){
12255  FTYPE gammafinal,qsqfinal;
12256  if(recomputegamma) gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammafinal,&qsqfinal);
12257  else gammafinal=gamma;
12258  FTYPE uradt=gammafinal/(ptrgeom->alphalapse); // u^t = gamma/alphalapse
12259  pin[NRAD] = uu[NRAD]/uradt; // nradinradframe * urad[TT] / uradt
12260  }
12261  else{
12262  // if failed to get solution, can't trust \gamma, so revert to thermal photons
12263  pin[NRAD] = calc_LTE_NfromE(Erf);
12264  }
12265 #endif
12266 
12267 
12268 
12269 
12270  if(debugfail>=2){
12271  static long int nstepold=-1;
12272  if(nstep!=nstepold && nstep%100==0 && ptrgeom->i==0 && ptrgeom->j==0 && ptrgeom->k==0 && steppart==0){
12273  nstepold=nstep;
12274  dualfprintf(fail_file,"numyvarneg=%lld numyvarbig=%lld numErneg=%lld nummod=%lld : nstep=%ld\n",numyvarneg,numyvarbig,numErneg,nummod,nstep);
12275  }
12276  }
12277 
12278 
12279  if(DORADFIXUPS==1 || allowlocalfailurefixandnoreport==0){
12280  // KORALTODO: Problem is fixups can average across shock or place where (e.g.) velocity changes alot, and averaging diffuses shock and can leak-out more failures.
12281  }
12282  else{
12283  // CASE reductions (so set as no failure so fixups don't operate -- but might also want to turn off CHECKINVERSIONRAD else that routine won't know when to ignore bad U->P->U cases.)
12284  if(*lpflagrad==0) *lpflagrad=UTOPRIMRADNOFAIL;
12285  else *lpflagrad=UTOPRIMRADFAILFIXEDUTOPRIMRAD; //UTOPRIMRADNOFAIL;
12286  }
12287 
12288  return 0;
12289 
12290 
12291 
12292 }
12293 
12294 
12300 int u2p_rad_new(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, int whichcap, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad)
12301 {
12302  static long long int numyvarneg,numyvarbig,numErneg,nummod;
12303  int recomputegamma=0;
12304 
12305 #if(WHICHVEL!=VELREL4)
12306  dualfprintf(fail_file,"u2p_rad() only setup for relative 4-velocity, currently.\n");
12307  myexit(137432636);
12308 #endif
12309 
12310 
12311  // copy over pin so pin isn't modified until end
12312  int pliter,pl;
12313  FTYPE pp[NPR];
12314  PLOOP(pliter,pl) pp[pl]=pin[pl];
12315 
12317  //
12318  // Prepare inversion from U->p for radiation assuming M1 closure
12319  //
12321 
12322  *lpflagrad=UTOPRIMRADNOFAIL;
12323 
12324  FTYPE Er,Utildesq,Utildecon[NDIM];
12325  compute_ZAMORAD(uu, ptrgeom, &Er, &Utildesq, Utildecon);
12326 
12327  // \gamma_{\rm rad}^2 : only 1 root
12328  FTYPE gammasq,gamma,qsq;
12329  FTYPE gammamax=gammamaxrad;
12330  FTYPE gammamaxsq=gammamax*gammamax;
12331  FTYPE ylimit = 16.0*gammamaxsq*(gammamaxsq-1.0)/((4.0*gammamaxsq-1.0)*(4.0*gammamaxsq-1.0));
12332 
12333  FTYPE yvar;
12334  int didmod=0;
12335  int didmodEr=0,didmody=0,gotbigy=0;
12336 
12338  //
12339  // Get y
12340  //
12342  if(Er>ERADLIMIT){ // then good solution. Avoid caps during implicit solver to allow progress on solution in smooth way.
12343  // E_r^2
12344  FTYPE Ersq=Er*Er;
12345  // y
12346  yvar = Utildesq / (ERADLIMIT*ERADLIMIT+Ersq);
12347  }
12348  else{// then bad solution
12349  // dualfprintf(fail_file,"Er=%26.20g<ERADLIMIT=%26.20g yvar=%26.20g Utildesq=%26.20g Ersq=%26.20g\n",Er,ERADLIMIT,yvar,Utildesq,Ersq);
12350  Er=ERADLIMIT;
12351  yvar = ylimit; // used
12352  didmod=1;
12353  didmodEr=1;
12354  numErneg++;
12355  }
12356 
12357 
12359  //
12360  // Get \gamma and \gamma^2 from y
12361  //
12363  FTYPE Erf,pr;
12364  if(yvar<0.0){
12365  // dualfprintf(fail_file,"Er=%26.20g yvar=%26.20g<0.0 Utildesq=%26.20g Ersq=%26.20g\n",Er,yvar,Utildesq,Ersq);
12366  gammasq = 1.0;
12367  gamma = 1.0;
12368  if(didmodEr) didmod=didmody=1;
12369  // didmod=1; // assume when y<0 that don't need to modify how Erf computed (i.e. Er is ok)
12370  numyvarneg++;
12371  pr = Er/(4.0*gammasq-1.0);
12372  // radiation frame energy density
12373  Erf = pr/(4.0/3.0-1.0);
12374  }
12375  else if(yvar>ylimit){ // beyond gamma limit, then rescale gamma
12376  gammasq = gammamaxsq;
12377  gamma = gammamax;
12378  didmod=1;
12379  didmody=1;
12380  gotbigy=1;
12381  numyvarbig++;
12382 
12383  pr = Er/(4.0*gammasq-1.0);
12384  // radiation frame energy density
12385  Erf = pr/(4.0/3.0-1.0);
12386  // dualfprintf(fail_file,"yvar=%g>%g Ersq=%g gamma=%g\n",yvar,ylimit,Ersq,gamma);
12387  }
12388  else{ // normal solution
12389  gammasq = (2.0 - yvar + sqrt(4.0-3.0*yvar))/ (4.0*(1.0-yvar));
12390  gamma=sqrt(gammasq);
12391 
12392  pr = Er/(4.0*gammasq-1.0);
12393  // radiation frame energy density
12394  Erf = pr/(4.0/3.0-1.0);
12395  }
12396 
12397 
12398 
12400  //
12401  // Get uconrel and Erf from gamma,gammasq, and Utildecon
12402  //
12404  FTYPE urfconrel[NDIM]={0.0};
12405  int jj;
12406  // if(1||gammamaxrad>0.9*GAMMAMAXRADIMPLICITSOLVER || Er>=ERADLIMIT){ // then good solution. Avoid caps during implicit solver to allow progress on solution in smooth way.
12407  if(didmody==0 && didmodEr==0){ // then good solution
12408 
12409  // radiation frame relativity 4-velocity
12410  SLOOPA(jj) urfconrel[jj] = gamma*(Utildecon[jj]/(4.0*pr*gammasq));
12411 
12412  //if(startpos[1]+ptrgeom->i==131 && startpos[2]+ptrgeom->j==19) dualfprintf(fail_file,"0didmod=%d : urfconrel=%g %g %g : %g : pr=%g Er=%g Ersq=%g yvar=%g Utildesq=%g\n",didmod,urfconrel[1],urfconrel[2],urfconrel[3],gamma,pr,Er,Er*Er,yvar,Utildesq);
12413  }
12414  else{ // fixes in case when Er<ERADLIMIT (whether or not y is modified)
12415  if(whichcap==CAPTYPEFIX1 || whichcap==CAPTYPEFIX2){
12416 
12417  // override if Er<0 originally since otherwise out of control rise in Erf
12418  // if(didmodEr || yvar<-NUMEPSILON || yvar>=2.0){
12419  if(didmodEr && whichcap==CAPTYPEFIX1){
12420  Er = ERADLIMIT;
12421  Erf = ERADLIMIT;
12422  gamma=1.0;
12423  // radiation frame relativity 4-velocity
12424  SLOOPA(jj) urfconrel[jj] = 0.0;
12425  // If E_r<0, then can't trust E_r and Erf is arbitrary. Choose instead first urfconrel to be maximum gamma as pointed in same 4-velocity direction as from Utildecon over previous Erf or u_g just to set scale
12426  // But better to not trust to avoid run-away energy creation
12427  }
12428  else{
12429  // if(yvar<1.0&&0||1){
12430  if(yvar<1.0&&0){
12431  // below sticks to what would end up like normal velocity scale.
12432  SLOOPA(jj) urfconrel[jj] = gamma*(Utildecon[jj]/(4.0*pr*gammasq));
12433  if(yvar>=1.0) SLOOPA(jj) urfconrel[jj]*=gamma; // fake to pretend very high gamma that we are coming from.
12434  }
12435  else{
12436  // if yvar>=1.0, then can't trust that gamma will rescale urfconrel into proper gamma>>1 range, so force.
12437  // Get urfconrel in same direction as Utildecon
12438  FTYPE Utildeabs=0.5*(sqrt(fabs(Utildesq))+fabs(Er)+ERADLIMIT);
12439  SLOOPA(jj) urfconrel[jj] = gamma*Utildecon[jj]/Utildeabs; // gives something that gives back ~gamma when using gamma_calc_fromuconrel()
12440  }
12441 
12442  // now get gamma for this fake urfconrel that is so-far only very roughly expected to be correct.
12443  FTYPE gammanew,qsqnew;
12444  gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammanew,&qsqnew);
12445  // if(gammanew<gammamax || gammanew<10.0){
12446  // if(gammanew<10.0 || gammanew>1000.0){
12447  // dualfprintf(fail_file,"gamma=%g gammanew=%g %g %g %g\n",gamma,gammanew,Utildecon[1],Utildecon[2],Utildecon[3]);
12448  // }
12449 
12450  // rescale, assuming want to be gammamax
12451  if(gammanew>1.0){
12452  FTYPE fvar=sqrt((gammamax*gammamax-1.0)/(gammanew*gammanew-1.0));
12453  SLOOPA(jj) urfconrel[jj] *= fvar;
12454  // verify
12455  FTYPE gammaneworig=gammanew;
12456  gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammanew,&qsqnew);
12457  // dualfprintf(fail_file,"VERIFY: gamma=%g gammanew=%g->%g fvar=%g\n",gamma,gammaneworig,gammanew,fvar);
12458  gamma=gammanew;
12459  gammasq=gammanew*gammanew;
12460  qsq=qsqnew;
12461  }
12462  else{
12463  SLOOPA(jj) urfconrel[jj] *= 0.0;
12464  gamma=1.0;
12465  gammasq=1.0;
12466  qsq=0.0;
12467  }
12468 
12469 
12470  // Get Er independent of R^t_t when hit limits when wanting Jacobian, so Jacobian doesn't NAN-out when taking differences and drop-outs in Erf lead to err function dominated by uu0 (and less often, G) and unaffected by the uu we are changing.
12471  if(whichcap==CAPTYPEFIX2 || yvar>=1.0-100.0*NUMEPSILON){ // don't use, just trust Er>0. Kinda works to set to if(1), but leads to some artifacts near where suddenly R^t_t would give different result for Er.
12472  //FTYPE utildesq=1.0+qsq;
12473  //pr=gamma*Utildesq/(4.0*gammasq) / (utildesq);
12474 
12475  // This determination of Er and pr connects continuously with y<=ylimit case no matter what original Er was.
12476  Er = ERADLIMIT + sqrt(fabs(Utildesq)/ylimit);
12477  pr=Er/(4.0*gammasq-1.0);
12478  // Get Erf
12479  FTYPE Erforig=Erf;
12480  Erf = pr/(4.0/3.0-1.0);
12481 
12482  // only modify Erf if really used as solution, not just Jacobian
12483  if(Erforig<Erf && whichcap==CAPTYPEFIX1) Erf=Erforig;
12484  }
12485  }
12486 
12487  }// endif capfixtype1
12488  else if(whichcap==CAPTYPEBASIC){
12489 
12490 
12491  if(didmodEr){
12492  // This just rejects entire radiative solution and makes it up. Bit extreme, but works. But leaves Erf having lowest values in spots where radiation just slightly went beyond speed of light.
12493  // However, this is most reasonable since if E_r<0, that means radiative energy is in another cell. If fill this cell with gammamax version of Erf using Utildesq, then adding energy, and situation can blow-up fast.
12494  Erf = ERADLIMIT;
12495  gamma=1.0;
12496  // radiation frame relativity 4-velocity
12497  SLOOPA(jj) urfconrel[jj] = 0.0;
12498  }
12499  else{
12500  // radiation frame relativity 4-velocity (using pr>0 and chosen gamma,gammasq)
12501  SLOOPA(jj) urfconrel[jj] = gamma*(Utildecon[jj]/(4.0*pr*gammasq));
12502 
12503  // Get resulting gamma and fix \tilde{u}^i, but don't modify Erf.
12504  FTYPE gammanew,qsqnew;
12505  // gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammanew,&qsqnew);
12506  gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammanew,&qsqnew);
12507  // dualfprintf(fail_file,"didmod: gamma=%g gammanew=%g\n",gamma,gammanew);
12508 
12509  // rescale, assuming want to be gamma that chose in previous section
12510  if(gammanew>1.0){
12511  FTYPE fvar=sqrt((gammasq-1.0)/(gammanew*gammanew-1.0));
12512  SLOOPA(jj) urfconrel[jj] *= fvar;
12513  }
12514  else{
12515  SLOOPA(jj) urfconrel[jj] *= 0.0;
12516  }
12517 
12518  // don't modify Erf if E_r was positive so that only had to rescale y (even if rescaled down from y>1 or gamma^2<0)
12519  // pr = Er/(4.0*gammanew*gammanew-1.0);
12520  // // radiation frame energy density
12521  // Erf = pr/(4.0/3.0-1.0);
12522 
12523 
12524  // if(startpos[1]+ptrgeom->i==131 && startpos[2]+ptrgeom->j==19) dualfprintf(fail_file,"didmod=%d : urfconrel=%g %g %g : %g %g\n",didmod,urfconrel[1],urfconrel[2],urfconrel[3],gamma,gammanew);
12525  }
12526  }
12527  else{
12528 #if(PRODUCTION==0)
12529  dualfprintf(fail_file,"No such whichcap=%d\n",whichcap);
12530  myexit(234534634);
12531 #endif
12532  }
12533  }
12534 
12535  // if(startpos[1]+ptrgeom->i==131 && startpos[2]+ptrgeom->j==19){
12536  // dualfprintf(fail_file,"AFTER urfconrel=%g %g %g : %g\n",urfconrel[1],urfconrel[2],urfconrel[3],gamma);
12537  // dualfprintf(fail_file,"AFTER2 urfconrel2=%g %g %g : %g\n",urfconrel[1]*sqrt(fabs(ptrgeom->gcov[GIND(1,1)])),urfconrel[2]*sqrt(fabs(ptrgeom->gcov[GIND(2,2)])),urfconrel[3]*sqrt(fabs(ptrgeom->gcov[GIND(3,3)])),gamma);
12538  // }
12539 
12540 
12542  //
12543  //new primitives (only uses urfcon[1-3])
12544  //
12546  pin[PRAD0]=Erf;
12547  pin[PRAD1]=urfconrel[1];
12548  pin[PRAD2]=urfconrel[2];
12549  pin[PRAD3]=urfconrel[3];
12550 
12551 
12552 
12554  //
12555  // INVERT to get Number density of photons in radiation frame
12556  //
12558 #if(EVOLVENRAD&&NRAD>0)
12559  if(*lpflagrad==UTOPRIMRADNOFAIL){
12560  FTYPE gammafinal,qsqfinal;
12561  if(recomputegamma) gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammafinal,&qsqfinal);
12562  else gammafinal=gamma;
12563  recomputegamma=0; // already recomputed, so can avoid another recomputation
12564  FTYPE uradt=gammafinal/(ptrgeom->alphalapse); // u^t = gamma/alphalapse
12565  pin[NRAD] = uu[NRAD]/uradt; // nradinradframe * urad[TT] / uradt
12566  }
12567  else{
12568  // if failed to get solution, can't trust \gamma, so revert to thermal photons
12569  pin[NRAD] = calc_LTE_NfromE(Erf);
12570  }
12571 #endif
12572 
12573 
12574 
12576  //
12577  // INVERT floor advectors
12578  //
12580 #if(DOYFL==2 && (YFL4>=0 || YFL5>=0))
12581  // if failed to get solution, can't trust \gamma, so evolution of floor wil be itself bad, but assume CASE reductions reasonable
12582  // But, for scalars, this primitive is ultimately multiplied by uradt itself, so whatever uradt is, the conserved quantity is evolved/fluxed correctly/conservatively
12583  if(1){
12584  FTYPE gammafinal,qsqfinal;
12585  if(recomputegamma) gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammafinal,&qsqfinal);
12586  else gammafinal=gamma;
12587  FTYPE uradt=gammafinal/(ptrgeom->alphalapse); // u^t = gamma/alphalapse
12588  if(YFL4>=0){
12589  pin[YFL4] = -uu[YFL4]/uradt; // -uu[YFLx]/u^t // NOTEMARK: Same sign as in other places like utoprimgen.c and fixup.c
12590  if(pin[YFL4]<ERADLIMIT) pin[YFL4]=ERADLIMIT; // floor on floor to avoid large gradients in flux that lead to crazy large values.
12591  }
12592  if(YFL5>=0) pin[YFL5] = uu[YFL5]/uradt; // uu[YFLx]/u^t
12593  }
12594 #endif
12595 
12596 
12597 
12598 
12599 
12600 
12601 
12602 
12603 
12604  // dualfprintf(fail_file,"didmod=%d\n",didmod);
12605 
12606  // make sure E_r no larger than starting value
12607  if(didmod==1){
12608  nummod++;
12609  if(didmodEr){
12610  *lpflagrad=UTOPRIMRADFAILERFNEG;
12611  }
12612  else{
12613  if(gotbigy) *lpflagrad=UTOPRIMRADFAILGAMMAHIGH;
12614  else *lpflagrad=UTOPRIMRADFAILCASE2A; // used to detect if modified primitives to not be consistent with inputted uu
12615  }
12616  }
12617 
12618 
12619 
12620 #if(PRODUCTION==0)
12621  if(debugfail>=2){
12622  static long int nstepold=-1;
12623  if(nstep!=nstepold && nstep%100==0 && ptrgeom->i==0 && ptrgeom->j==0 && ptrgeom->k==0 && steppart==0){
12624  nstepold=nstep;
12625  dualfprintf(fail_file,"numyvarneg=%lld numyvarbig=%lld numErneg=%lld nummod=%lld : nstep=%ld\n",numyvarneg,numyvarbig,numErneg,nummod,nstep);
12626  }
12627  }
12628 #endif
12629 
12630  // interpret certain failure modes (below, these are treated as soft failures only processed by fixup_utoprim()
12631  if(gotbigy) *lpflagrad=UTOPRIMRADFAILGAMMAHIGH; // softish failure where we will fixup_utoprim() urad^t but not Erf
12632  else if(didmodEr) *lpflagrad=UTOPRIMRADFAILERFNEG; // softish failure, passes through until fixup_utoprim() where adjusted
12633 
12634 
12635  if(DORADFIXUPS==1 || allowlocalfailurefixandnoreport==0){
12636  // KORALTODO: Problem is fixups can average across shock or place where (e.g.) velocity changes alot, and averaging diffuses shock and can leak-out more failures.
12637  }
12638  else{
12639  // CASE reductions (so set as no failure so fixups don't operate -- but might also want to turn off CHECKINVERSIONRAD else that routine won't know when to ignore bad U->P->U cases.)
12640  if(*lpflagrad==0) *lpflagrad=UTOPRIMRADNOFAIL;
12641  else if(gotbigy) *lpflagrad=UTOPRIMRADFAILGAMMAHIGH; // softish failure where we will fixup_utoprim() urad^t but not Erf
12642  else if(didmodEr) *lpflagrad=UTOPRIMRADFAILERFNEG; // softish failure, passes through until fixup_utoprim() where adjusted
12643  else *lpflagrad=UTOPRIMRADFAILFIXEDUTOPRIMRAD; //UTOPRIMRADNOFAIL;
12644  }
12645 
12646  return 0;
12647 
12648 
12649 
12650 }
12651 
12653 static int compute_ZAMORAD(FTYPE *uu, struct of_geom *ptrgeom, FTYPE *Er, FTYPE *Utildesq, FTYPE *Utildecon)
12654 {
12655  int jj,kk;
12656  FTYPE etacov[NDIM],etacon[NDIM];
12657  FTYPE Ucon[NDIM],Ucov[NDIM],Utildecov[NDIM];
12658 
12659  // dualfprintf(fail_file,"uu=%g %g %g %g\n",uu[URAD0],uu[URAD1],uu[URAD2],uu[URAD3]);
12660 
12661  // \eta_\mu
12662  etacov[TT] = -ptrgeom->alphalapse;
12663  SLOOPA(jj) etacov[jj]=0.0;
12664  // \eta^\mu
12665  raise_vec(etacov,ptrgeom,etacon); // could use ptrgeom->beta
12666 
12667  // U_\mu = -R^\nu_\mu \eta_\nu = \alpha R^t_\mu
12668  DLOOPA(jj) Ucov[jj] = ptrgeom->alphalapse*uu[URAD0+jj];
12669  // U^\mu
12670  raise_vec(Ucov,ptrgeom,Ucon);
12671 
12672  // \tilde{U}^\mu = j^\mu_\nu U^\nu = (\delta^\mu_\nu + \eta^\mu \eta_\nu) U^\nu : ZAMO frame momentum
12673  DLOOPA(jj) Utildecon[jj]=0.0;
12674  DLOOP(jj,kk) Utildecon[jj] += (delta(jj,kk) + etacon[jj]*etacov[kk])*Ucon[kk];
12675  // \tilde{U}_\mu
12676  lower_vec(Utildecon,ptrgeom,Utildecov);
12677 
12678  // \tilde{U}^2 = \tilde{U}^\mu \tilde{U}_\mu
12679  *Utildesq=0.0;
12680  DLOOPA(jj) *Utildesq += Utildecon[jj]*Utildecov[jj];
12681 
12682  // -Er = -R^\nu_\mu \eta_\nu \eta^\mu = U_\mu \eta^\mu = alpha R^t_\mu \eta^\mu : ZAMO frame energy
12683  *Er=0.0;
12684  DLOOPA(jj) *Er += -Ucov[jj]*etacon[jj];
12685 
12686 
12687  return(0);
12688 }
12689 
12690 
12691 // 0 or 1
12692 // generally, should have TRYCOLD=1 as most general way to deal with failure
12693 #define TRYCOLD 1
12694 
12695 // for debugging
12698 
12729 int u2p_rad_orig(int showmessages, int allowlocalfailurefixandnoreport, FTYPE gammamaxrad, FTYPE *uu, FTYPE *pin, struct of_geom *ptrgeom,PFTYPE *lpflag, PFTYPE *lpflagrad)
12730 {
12731  int jj,kk;
12732  FTYPE pp[NPR];
12733  int pliter,pl;
12734 
12735  PLOOP(pliter,pl) globaluu[pl]=uu[pl];
12736  PLOOP(pliter,pl) globalpin[pl]=pin[pl];
12737 
12738  if(WHICHVEL!=VELREL4){
12739  dualfprintf(fail_file,"u2p_rad() only setup for relative 4-velocity, currently.\n");
12740  myexit(137432636);
12741  }
12742 
12743 
12744  // copy over pin so pin isn't modified until end
12745  PLOOP(pliter,pl) pp[pl]=pin[pl];
12746 
12748  //
12749  // Prepare inversion from U->p for radiation assuming M1 closure
12750  //
12752 
12753  *lpflagrad=UTOPRIMRADNOFAIL;
12754 
12755 
12756  //conserved - R^t_mu
12757  FTYPE Avcov[NDIM]={uu[URAD0],uu[URAD1],uu[URAD2],uu[URAD3]};
12758  //indices up - R^tmu
12759  FTYPE Avcon[NDIM];
12760  indices_12(Avcov,Avcon,ptrgeom);
12761 
12762 
12763  FTYPE gammarel2,delta,numerator,divisor;
12764  FTYPE Erf;
12765  FTYPE urfconrel[NDIM];
12766 
12767 
12768  if(EOMRADTYPE==EOMRADEDD){
12769  // NOTEMARK: Can't use normal inversion that assumes R^t_i are independently evolved because they will generally lead to different velocity than fluid.
12770 
12771  // radiation is same as fluid gamma (assume fluid has already been inverted)
12772  urfconrel[1]=pp[PRAD1]=pp[U1];
12773  urfconrel[2]=pp[PRAD2]=pp[U2];
12774  urfconrel[3]=pp[PRAD3]=pp[U3];
12775 
12776  // get gammarel2
12777  FTYPE gammarel,qsq;
12778  gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammarel,&qsq);
12779  gammarel2=gammarel*gammarel;
12780 
12781  FTYPE alpha=ptrgeom->alphalapse; //sqrt(-1./ptrgeom->gcon[GIND(0,0)]);
12782  // get energy density in fluid frame from lab-frame
12783  Erf=3.*Avcon[0]*alpha*alpha/(4.*gammarel2-1.0); // JCM
12784 
12785  }
12786  else if(EOMRADTYPE==EOMRADM1CLOSURE){
12787 
12788  // get \gamma^2 for relative 4-velocity
12789  get_m1closure_gammarel2(showmessages,ptrgeom,Avcon,Avcov,&gammarel2,&delta,&numerator,&divisor);
12790 
12791  if(0){
12792  // testing
12793  FTYPE Avconnew[NDIM]={Avcon[0],Avcon[1],Avcon[2],Avcon[3]};
12794  FTYPE urfconrelnew[NDIM];
12795  FTYPE gammarel2new,deltanew,numeratornew,divisornew,Erfnew;
12796  // get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avconnew,&gammarel2new,&deltanew,&numeratornew,&divisornew,&Erfnew,urfconrelnew);
12797  get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avconnew,Avcov,NULL,&deltanew,&numeratornew,&divisornew,&Erfnew,urfconrelnew);
12798  }
12799 
12800 
12801 
12802  // get E in radiation frame
12803  get_m1closure_Erf(ptrgeom,Avcon,gammarel2,&Erf);
12804  FTYPE Erforig=Erf;
12805 
12806  // get relative 4-velocity
12807  if(CASECHOICE==JONCHOICE) get_m1closure_urfconrel(showmessages,allowlocalfailurefixandnoreport,ptrgeom,pp,Avcon,Avcov,gammarel2,delta,numerator,divisor,&Erf,urfconrel,lpflag,lpflagrad);
12808  else if(CASECHOICE==OLEKCHOICE) get_m1closure_urfconrel_olek(showmessages,allowlocalfailurefixandnoreport,ptrgeom,pp,Avcon,Avcov,gammarel2,delta,&Erf,urfconrel,lpflag,lpflagrad);
12809 
12810 #if(0)
12811  // TESTING:
12812  FTYPE Erf2=Erforig,urfconrel2[NDIM];
12813  get_m1closure_urfconrel_olek(showmessages,allowlocalfailurefixandnoreport,ptrgeom,pp,Avcon,Avcov,gammarel2,delta,&Erf2,urfconrel2,lpflag,lpflagrad);
12814  FTYPE ERRORCHECK;
12815  ERRORCHECK=1E-1;
12816  if( fabs(Erf2-Erf)/(fabs(Erf2)+fabs(Erf))>ERRORCHECK || fabs(urfconrel2[1]-urfconrel[1])/(fabs(urfconrel2[1])+fabs(urfconrel[1]))>ERRORCHECK || fabs(urfconrel2[2]-urfconrel[2])/(fabs(urfconrel2[2])+fabs(urfconrel[2]))>ERRORCHECK || fabs(urfconrel2[3]-urfconrel[3])/(fabs(urfconrel2[3])+fabs(urfconrel[3]))>ERRORCHECK){
12817  dualfprintf(fail_file,"JONVSOLEK: ijk=%d %d %d : nstep=%ld steppart=%d : %g %g %g %g : %g %g %g %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,Erf,urfconrel[1],urfconrel[2],urfconrel[3],Erf2,urfconrel2[1],urfconrel2[2],urfconrel2[3]);
12818  }
12819  ERRORCHECK=0.4;
12820  if( fabs(Erf2-Erf)/(fabs(Erf2)+fabs(Erf))>ERRORCHECK || fabs(urfconrel2[1]-urfconrel[1])/(fabs(urfconrel2[1])+fabs(urfconrel[1]))>ERRORCHECK || fabs(urfconrel2[2]-urfconrel[2])/(fabs(urfconrel2[2])+fabs(urfconrel[2]))>ERRORCHECK || fabs(urfconrel2[3]-urfconrel[3])/(fabs(urfconrel2[3])+fabs(urfconrel[3]))>ERRORCHECK){
12821  dualfprintf(fail_file,"JONVSOLEK: ijk=%d %d %d : nstep=%ld steppart=%d : %g %g %g %g : %g %g %g %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,Erf,urfconrel[1],urfconrel[2],urfconrel[3],Erf2,urfconrel2[1],urfconrel2[2],urfconrel2[3]);
12822  }
12823 #endif
12824 
12825  }// end if M1
12826  else{
12827  dualfprintf(fail_file,"No such EOMRADTYPE=%d in u2p_rad()\n",EOMRADTYPE);
12828  myexit(368322162);
12829  }
12830 
12831 
12832  //new primitives (only uses urfcon[1-3])
12833  pin[PRAD0]=Erf;
12834  pin[PRAD1]=urfconrel[1];
12835  pin[PRAD2]=urfconrel[2];
12836  pin[PRAD3]=urfconrel[3];
12837 
12839  //
12840  // INVERT to get Number density of photons in radiation frame
12841  //
12843 #if(EVOLVENRAD&&NRAD>0)
12844  if(*lpflagrad==UTOPRIMRADNOFAIL){
12845  FTYPE gammafinal,qsqfinal;
12846  gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammafinal,&qsqfinal);
12847  FTYPE uradt=gammafinal/(ptrgeom->alphalapse); // u^t = gamma/alphalapse
12848  pin[NRAD] = uu[NRAD]/uradt; // nradinradframe * urad[TT] / uradt
12849  }
12850  else{
12851  // if failed to get solution, can't trust \gamma, so revert to thermal photons
12852  pin[NRAD] = calc_LTE_NfromE(Erf);
12853  }
12854 #endif
12855 
12856 
12857 
12859  //
12860  // INVERT floor advectors
12861  //
12863 #if(DOYFL==2 && (YFL4>=0 || YFL5>=0))
12864  // if failed to get solution, can't trust \gamma, so evolution of floor wil be itself bad, but assume CASE reductions reasonable
12865  // But, for scalars, this primitive is ultimately multiplied by uradt itself, so whatever uradt is, the conserved quantity is evolved/fluxed correctly/conservatively
12866  if(1){
12867  FTYPE gammafinal,qsqfinal;
12868  gamma_calc_fromuconrel(&pin[URAD1-1],ptrgeom,&gammafinal,&qsqfinal);
12869  FTYPE uradt=gammafinal/(ptrgeom->alphalapse); // u^t = gamma/alphalapse
12870  if(YFL4>=0){
12871  pin[YFL4] = -uu[YFL4]/uradt; // -uu[YFLx]/u^t // NOTEMARK: Same sign as in other places like utoprimgen.c and fixup.c
12872  if(pin[YFL4]<ERADLIMIT) pin[YFL4]=ERADLIMIT; // floor on floor to avoid large gradients in flux that lead to crazy large values.
12873  }
12874  if(YFL5>=0) pin[YFL5] = uu[YFL5]/uradt; // uu[YFLx]/u^t
12875  }
12876 #endif
12877 
12878  // DLOOPA(jj){
12879  // if(!isfinite(pin[PRAD0+jj])){
12880  // dualfprintf(fail_file,"caughtnan: jj=%d : ijk=%d %d %d\n",jj,ptrgeom->i,ptrgeom->j,ptrgeom->k);
12881  // }
12882  // }
12883 
12884  if(DORADFIXUPS==1 || allowlocalfailurefixandnoreport==0){
12885  // KORALTODO: Problem is fixups can average across shock or place where (e.g.) velocity changes alot, and averaging diffuses shock and can leak-out more failures.
12886  }
12887  else{
12888  // CASE reductions (so set as no failure so fixups don't operate -- but might also want to turn off CHECKINVERSIONRAD else that routine won't know when to ignore bad U->P->U cases.)
12889  if(*lpflagrad==0) *lpflagrad=UTOPRIMRADNOFAIL;
12890  else *lpflagrad=UTOPRIMRADFAILFIXEDUTOPRIMRAD; //UTOPRIMRADNOFAIL;
12891  }
12892 
12893  return 0;
12894 }
12895 
12896 
12897 
12898 
12899 
12901 static int opacity_interpolated_urfconrel(FTYPE tautotmax, FTYPE *pp,struct of_geom *ptrgeom,FTYPE *Avcon, FTYPE Erf,FTYPE gammarel2, FTYPE *Erfnew, FTYPE *urfconrel)
12902 {
12903  int jj;
12904  FTYPE alpha=ptrgeom->alphalapse; //sqrt(-1./ptrgeom->gcon[GIND(0,0)]);
12905 
12906  // dualfprintf(fail_file,"Erf=%g gammarel2=%g\n",Erf,gammarel2);
12907 
12908  FTYPE gammafluid,gammarel2fluid,qsqfluid,Erffluid;
12909  gamma_calc_fromuconrel(&pp[U1-1],ptrgeom,&gammafluid,&qsqfluid);
12910  gammarel2fluid=gammafluid*gammafluid;
12911  get_m1closure_Erf(ptrgeom, Avcon, gammarel2fluid, &Erffluid);
12912  if(Erffluid<ERADLIMIT) Erffluid=ERADLIMIT;
12913 
12914  FTYPE gammarad,gammarel2rad,qsqrad,Erfrad;
12915  gamma_calc_fromuconrel(&pp[URAD1-1],ptrgeom,&gammarad,&qsqrad);
12916  gammarel2rad=gammarad*gammarad;
12917  get_m1closure_Erf(ptrgeom, Avcon, gammarel2rad, &Erfrad);
12918  if(Erfrad<ERADLIMIT) Erfrad=ERADLIMIT;
12919 
12920  // now set urfconrel. Choose fluid if tautotmax>=2/3 (updated fluid value), while choose previous radiation value (i.e. static!)
12921  // limit for interpolation below
12922  // below makes no sense because even for tau<<1 Erf and uradcon^i can be very different, so can end-up using too much of fluid version
12923  // FTYPE tautotmaxlim=MIN(fabs(tautotmax),1.0);
12924  FTYPE tautotmaxlim=(1.0 - 1.0/(1.0+fabs(tautotmax)));
12925  // done with Erf, so get Erfnew (Erf and *Erfnew might be same variable, but Erf passed by value so changing *Erfnew won't change Erf anyways)
12926  *Erfnew = (1.0-tautotmaxlim)*Erfrad + tautotmaxlim*Erffluid;
12927  SLOOPA(jj) urfconrel[jj] = (1.0-tautotmaxlim)*pp[URAD1+jj-1] + tautotmaxlim*pp[U1+jj-1];
12928 
12929  dualfprintf(fail_file,"i=%d tautotmax=%g tautotmaxlim=%g\n",ptrgeom->i,tautotmax,tautotmaxlim);
12930  SLOOPA(jj) dualfprintf(fail_file,"jj=%d Erfrad=%g Erffluid=%g gammarad=%g gammafluid=%g Erfnew=%g urfconrel=%g\n",jj,Erfrad,Erffluid,gammarad,gammafluid,*Erfnew,urfconrel[jj]);
12931 
12932  return(0);
12933 }
12934 
12935 
12936 
12938 static int get_m1closure_gammarel2_old(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn)
12939 {
12940  FTYPE gamma2,gammarel2,delta,numerator,divisor;
12941 
12942  if(0){
12943  // has some catastrophic cancellation issue for non-moving velocity at very low E\sim 1E-92 (as in RADPULSE test if no temperature conversion)
12944 
12945  //g_munu R^tmu R^tnu
12946  int jj,kk;
12947  FTYPE gRR=0.0;
12948  DLOOP(jj,kk) gRR += ptrgeom->gcov[GIND(jj,kk)]*Avcon[jj]*Avcon[kk];
12949 
12950  //the quadratic equation for u^t of the radiation rest frame (urf[0])
12951  // Formed as solution for solving two equations (R^{t\nu} R^t_\nu(E,ut) and R^{tt}(E,ut)) for ut
12952  //supposed to provide two roots for (u^t)^2 of opposite signs
12953  FTYPE aa,b,c;
12954  aa=16.*gRR;
12955  b=8.*(gRR*ptrgeom->gcon[GIND(0,0)]+Avcon[0]*Avcon[0]);
12956  c=ptrgeom->gcon[GIND(0,0)]*(gRR*ptrgeom->gcon[GIND(0,0)]-Avcon[0]*Avcon[0]);
12957  delta=b*b-4.*aa*c;
12958 
12959  numerator=0.5*(-b-sqrt(delta));
12960  divisor=aa;
12961 
12962  gamma2=numerator/divisor; // lab-frame gamma^2
12963  //if unphysical try the other root
12964  if(gamma2<=0.){
12965  numerator=0.5*(-b+sqrt(delta));
12966  divisor=aa;
12967  gamma2= numerator/divisor;
12968  }
12969 
12970  *numeratorreturn=numerator;
12971  *divisorreturn=divisor;
12972  }
12973  // dualfprintf(fail_file,"GAMMA2CHECK: ijk=%d %d %d : %g %g : aa=%g b=%g c=%g : delta=%g gRR=%g Avcon0123=%g %g %g %g : gamma2=%g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,0.5*(-b-sqrt(delta))/aa,0.5*(-b+sqrt(delta))/aa,aa,b,c,delta,gRR,Avcon[0],Avcon[1],Avcon[2],Avcon[3],gamma2);
12974 
12975 
12976  else{
12977  // mathematica solution that avoids catastrophic cancellation when Rtt very small (otherwise above gives gamma2=1/2 oddly when gamma2=1) -- otherwise same as above
12978  // well, then had problems for R~1E-14 for some reason when near BH. Couldn't quickly figure out, so use no replacement of gv11.
12979  // see u2p_inversion.nb
12980  static FTYPE gctt, gv11, gv12, gv13, gv14, gv22, gv23, gv24, gv33, gv34, gv44, Rtt, Rtx, Rty, Rtz;
12981  gv11=ptrgeom->gcov[GIND(0,0)];
12982  gv12=ptrgeom->gcov[GIND(0,1)];
12983  gv13=ptrgeom->gcov[GIND(0,2)];
12984  gv14=ptrgeom->gcov[GIND(0,3)];
12985  gv22=ptrgeom->gcov[GIND(1,1)];
12986  gv23=ptrgeom->gcov[GIND(1,2)];
12987  gv24=ptrgeom->gcov[GIND(1,3)];
12988  gv33=ptrgeom->gcov[GIND(2,2)];
12989  gv34=ptrgeom->gcov[GIND(2,3)];
12990  gv44=ptrgeom->gcov[GIND(3,3)];
12991  Rtt=Avcon[0];
12992  Rtx=Avcon[1];
12993  Rty=Avcon[2];
12994  Rtz=Avcon[3];
12995  gctt=ptrgeom->gcon[GIND(0,0)];
12996 
12997  delta = (1. + 3.*gctt*gv11)*((Rtt)*(Rtt)) +
12998  6.*gctt*Rtt*(gv12*Rtx + gv13*Rty + gv14*Rtz) +
12999  3.*gctt*(gv22*((Rtx)*(Rtx)) + 2.*gv23*Rtx*Rty + gv33*((Rty)*(Rty)) +
13000  2.*gv24*Rtx*Rtz + 2.*gv34*Rty*Rtz + gv44*((Rtz)*(Rtz)));
13001 
13002  divisor=(gv11*((Rtt)*(Rtt)) + 2.*gv12*Rtt*Rtx + gv22*((Rtx)*(Rtx)) + 2.*gv13*Rtt*Rty +
13003  2.*gv23*Rtx*Rty + gv33*((Rty)*(Rty)) + 2.*(gv14*Rtt + gv24*Rtx + gv34*Rty)*Rtz +
13004  gv44*((Rtz)*(Rtz)));
13005 
13006  numerator=(-0.25*((1. + gctt*gv11)*((Rtt)*(Rtt)) +
13007  gctt*(gv22*((Rtx)*(Rtx)) + 2.*gv23*Rtx*Rty + gv33*((Rty)*(Rty)) +
13008  2.*gv24*Rtx*Rtz + 2.*gv34*Rty*Rtz + gv44*((Rtz)*(Rtz))) +
13009  Rtt*(2.*gctt*(gv12*Rtx + gv13*Rty + gv14*Rtz) +
13010  Sqrt(delta))));
13011 
13012  gamma2 = numerator/divisor;
13013  }
13014 
13015 
13017  //
13018  //cap on u^t
13019  //
13021  FTYPE alpha=ptrgeom->alphalapse;
13022 
13023 
13024  // get relative 4-velocity, that is always >=1 even in GR
13025  gammarel2 = gamma2*alpha*alpha;
13026 
13027  // check for machine error away from 1.0 that happens sometimes
13028  if(gammarel2>GAMMASMALLLIMIT && gammarel2<1.0){
13029  // if(debugfail>=2) dualfprintf(fail_file,"Hit machine error of gammarel2=%27.20g fixed to be 1.0\n",gammarel2);
13030  gammarel2=1.0;
13031  }
13032 
13033  // dualfprintf(fail_file,"gammarel2=%g gamma2=%g delta=%21.15g\n",gammarel2,gamma2,delta);
13034 
13035  *gammarel2return=gammarel2;
13036  *deltareturn=delta;
13037  *numeratorreturn=numerator;
13038  *divisorreturn=divisor;
13039  return(0);
13040 
13041 }
13042 
13043 
13044 
13045 
13046 
13047 
13048 
13049 
13050 
13051 
13052 
13053 
13055 static int get_m1closure_gammarel2(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn)
13056 {
13057  FTYPE gamma2,gammarel2,delta,numerator,divisor;
13058  FTYPE gamma2a,gamma2b;
13059 
13060  // mathematica solution that avoids catastrophic cancellation when Rtt very small (otherwise above gives gamma2=1/2 oddly when gamma2=1) -- otherwise same as above
13061  // well, then had problems for R~1E-14L for some reason when near BH. Couldn't quickly figure out, so use no replacement of gv11.
13062  // see u2p_inversion.nb
13063  static FTYPE gctt, gn11, gn12, gn13, gn14, gn22, gn23, gn24, gn33, gn34, gn44, Rtt, Rtx, Rty, Rtz, Rdtt, Rdtx, Rdty, Rdtz;
13064  gn11=ptrgeom->gcon[GIND(0,0)];
13065  gn12=ptrgeom->gcon[GIND(0,1)];
13066  gn13=ptrgeom->gcon[GIND(0,2)];
13067  gn14=ptrgeom->gcon[GIND(0,3)];
13068  gn22=ptrgeom->gcon[GIND(1,1)];
13069  gn23=ptrgeom->gcon[GIND(1,2)];
13070  gn24=ptrgeom->gcon[GIND(1,3)];
13071  gn33=ptrgeom->gcon[GIND(2,2)];
13072  gn34=ptrgeom->gcon[GIND(2,3)];
13073  gn44=ptrgeom->gcon[GIND(3,3)];
13074 
13075  Rtt=Avcon[0];
13076  Rtx=Avcon[1];
13077  Rty=Avcon[2];
13078  Rtz=Avcon[3];
13079 
13080  Rdtt=Avcov[0];
13081  Rdtx=Avcov[1];
13082  Rdty=Avcov[2];
13083  Rdtz=Avcov[3];
13084 
13085  gamma2a=(-0.25*(2.*Power(gn11,2)*Power(Rdtt,2) + (gn12*Rdtx + gn13*Rdty + gn14*Rdtz)*
13086  (gn12*Rdtx + gn13*Rdty + gn14*Rdtz + Sqrt(4.*Power(gn11,2)*Power(Rdtt,2) + Power(gn12*Rdtx + gn13*Rdty + gn14*Rdtz,2) +
13087  gn11*(8.*gn12*Rdtt*Rdtx + 3.*gn22*Power(Rdtx,2) + 8.*gn13*Rdtt*Rdty + 6.*gn23*Rdtx*Rdty + 3.*gn33*Power(Rdty,2) +
13088  8.*gn14*Rdtt*Rdtz + 6.*gn24*Rdtx*Rdtz + 6.*gn34*Rdty*Rdtz + 3.*gn44*Power(Rdtz,2)))) +
13089  gn11*(4.*gn12*Rdtt*Rdtx + gn22*Power(Rdtx,2) + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) + 2.*gn24*Rdtx*Rdtz +
13090  2.*gn34*Rdty*Rdtz + gn44*Power(Rdtz,2) + Rdtt*
13091  (4.*gn13*Rdty + 4.*gn14*Rdtz + Sqrt(4.*Power(gn11,2)*Power(Rdtt,2) + Power(gn12*Rdtx + gn13*Rdty + gn14*Rdtz,2) +
13092  gn11*(8.*gn12*Rdtt*Rdtx + 3.*gn22*Power(Rdtx,2) + 8.*gn13*Rdtt*Rdty + 6.*gn23*Rdtx*Rdty + 3.*gn33*Power(Rdty,2) +
13093  8.*gn14*Rdtt*Rdtz + 6.*gn24*Rdtx*Rdtz + 6.*gn34*Rdty*Rdtz + 3.*gn44*Power(Rdtz,2)))))))/
13094  (gn11*Power(Rdtt,2) + 2.*gn12*Rdtt*Rdtx + gn22*Power(Rdtx,2) + 2.*gn13*Rdtt*Rdty + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) +
13095  2.*(gn14*Rdtt + gn24*Rdtx + gn34*Rdty)*Rdtz + gn44*Power(Rdtz,2));
13096 
13097 
13098  if( gamma2a<GAMMASMALLLIMIT || !isfinite(gamma2a) ){
13099  gamma2b=(0.25*(-2.*Power(gn11,2)*Power(Rdtt,2) - 1.*gn11*(4.*gn12*Rdtt*Rdtx + gn22*Power(Rdtx,2) +
13100  Rdty*(4.*gn13*Rdtt + 2.*gn23*Rdtx + gn33*Rdty) + 2.*(2.*gn14*Rdtt + gn24*Rdtx + gn34*Rdty)*Rdtz + gn44*Power(Rdtz,2)) +
13101  gn11*Rdtt*Sqrt(4.*Power(gn11,2)*Power(Rdtt,2) + Power(gn12*Rdtx + gn13*Rdty + gn14*Rdtz,2) +
13102  gn11*(8.*gn12*Rdtt*Rdtx + 3.*gn22*Power(Rdtx,2) + 8.*gn13*Rdtt*Rdty + 6.*gn23*Rdtx*Rdty + 3.*gn33*Power(Rdty,2) +
13103  8.*gn14*Rdtt*Rdtz + 6.*gn24*Rdtx*Rdtz + 6.*gn34*Rdty*Rdtz + 3.*gn44*Power(Rdtz,2))) +
13104  (gn12*Rdtx + gn13*Rdty + gn14*Rdtz)*(-1.*gn12*Rdtx - 1.*gn13*Rdty - 1.*gn14*Rdtz +
13105  Sqrt(4.*Power(gn11,2)*Power(Rdtt,2) + Power(gn12*Rdtx + gn13*Rdty + gn14*Rdtz,2) +
13106  gn11*(8.*gn12*Rdtt*Rdtx + 3.*gn22*Power(Rdtx,2) + 8.*gn13*Rdtt*Rdty + 6.*gn23*Rdtx*Rdty + 3.*gn33*Power(Rdty,2) +
13107  8.*gn14*Rdtt*Rdtz + 6.*gn24*Rdtx*Rdtz + 6.*gn34*Rdty*Rdtz + 3.*gn44*Power(Rdtz,2))))))/
13108  (gn11*Power(Rdtt,2) + 2.*gn12*Rdtt*Rdtx + gn22*Power(Rdtx,2) + 2.*gn13*Rdtt*Rdty + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) +
13109  2.*(gn14*Rdtt + gn24*Rdtx + gn34*Rdty)*Rdtz + gn44*Power(Rdtz,2));
13110  gamma2=gamma2b;
13111  }
13112  else{
13113  // choose
13114  gamma2=gamma2a;
13115  }
13116 
13118  //
13119  //cap on u^t
13120  //
13122  FTYPE alpha=ptrgeom->alphalapse;
13123 
13124 
13125  // get relative 4-velocity, that is always >=1 even in GR
13126  gammarel2 = gamma2*alpha*alpha;
13127 
13128  // check for machine error away from 1.0 that happens sometimes
13129  if(gammarel2>GAMMASMALLLIMIT && gammarel2<1.0){
13130  // if(debugfail>=2) dualfprintf(fail_file,"Hit machine error of gammarel2=%27.20g fixed to be 1.0\n",gammarel2);
13131  gammarel2=1.0;
13132  }
13133 
13134  // dualfprintf(fail_file,"gammarel2=%g gamma2=%g delta=%21.15g\n",gammarel2,gamma2,delta);
13135 
13136  *gammarel2return=gammarel2;
13137  *deltareturn=delta=0;
13138  *numeratorreturn=numerator=0;
13139  *divisorreturn=divisor=0;
13140  return(0);
13141 
13142 }
13143 
13144 
13145 
13146 
13147 
13148 
13149 
13151 static int get_m1closure_Erf(struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE gammarel2, FTYPE *Erfreturn)
13152 {
13153  FTYPE alpha=ptrgeom->alphalapse;
13154 
13156  //
13157  // get initial attempt for Erf
13158  // If delta<0, then gammarel2=nan and Erf<RADLIMIT check below will fail as good.
13159  //
13161  *Erfreturn = 3.*Avcon[0]*alpha*alpha/(4.*gammarel2-1.0); // JCM
13162 
13163  return(0);
13164 }
13165 
13166 
13167 
13169 static int get_m1closure_urfconrel_old(int showmessages, int allowlocalfailurefixandnoreport, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *Avcon, FTYPE *Avcov, FTYPE gammarel2, FTYPE delta, FTYPE numerator, FTYPE divisor, FTYPE *Erfreturn, FTYPE *urfconrel, PFTYPE *lpflag, PFTYPE *lpflagrad)
13170 {
13171  FTYPE Erf=*Erfreturn; // get initial Erf
13172  FTYPE gammamax=GAMMAMAXRAD;
13173  FTYPE gammamaxfail=GAMMAMAXRADFAIL;
13174  int jj,kk;
13175 
13176 
13178  //
13179  // Fix-up inversion if problem with gamma (i.e. velocity) or energy density in radiation rest-frame (i.e. Erf)
13180  //
13182 
13184  //
13185  // First case is if gammarel>gammamax, then set gammarel=gammamax unless Erf<ERADLIMIT (~0) in which case set Erf=ERADLIMIT and gammarel=1.
13186  // Note, can't set urfcon[0]=gammamax in case gammamax still remains space-like, e.g. inside horizon if gammamax isn't big enough.
13187  //
13189 
13190  // NOTE: gammarel2 just below 1.0 already fixed to be =1.0
13191  int nonfailure=gammarel2>=1.0 && Erf>ERADLIMIT && gammarel2<=gammamax*gammamax/GAMMASMALLLIMIT/GAMMASMALLLIMIT;
13192  // falilure1 : gammarel2 normal, but already Erf<ERADLIMIT (note for M1 that gammarel2>=1/4 for any reasonable chance for correct non-zero Erf
13193  int failure1=Avcon[0]<0.0 || (gammarel2>0.0 && gammarel2<=0.25L && delta>=0.0 && divisor!=0.0) || numerator==0.0 || gammarel2>=1.0 && delta>=0.0 && divisor!=0.0 && Erf<ERADLIMIT;
13194  // gamma probably around 1
13195  int failure2=gammarel2<1.0 && gammarel2>0.0 && delta>=0.0;
13196  // i.e. all else, so not really used below.
13197  int failure3=gammarel2>gammamax*gammamax && Erf>=ERADLIMIT || gammarel2<0.0 || delta<0. || divisor==0.0 && numerator==0.0 || divisor==0.0 && numerator!=0.0;
13198 
13199 
13200 
13201  if(nonfailure){
13202  // get good relative velocity
13203  FTYPE gammarel=sqrt(gammarel2);
13204  FTYPE alpha=ptrgeom->alphalapse;
13205 
13206  SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
13207 
13208  *Erfreturn=Erf; // pass back new Erf to pointer
13209  return(0);
13210 
13211  // dualfprintf(fail_file,"NO failure: %g %g ijk=%d %d %d\n",Erf,gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13212  }
13213  else if(failure1){
13214  if(TRYCOLD){
13215  gammarel2=pow(1.0+10.0*NUMEPSILON,2.0);
13216  get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avcon,Avcov,&gammarel2,&delta,&numerator,&divisor,&Erf,urfconrel);
13217  }
13218  else{
13219  // Can't have Erf<0. Like floor on internal energy density. If leave Erf<0, then will drive code crazy with free energy.
13220  Erf=ERADLIMIT;
13221 
13222  SLOOPA(jj) urfconrel[jj] = 0.0; // consistent with gammarel2=1
13223  }
13224  if(1 || allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE3A;
13225  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE3A: normal gamma, but Erf<ERADLIMIT. ijk=%d %d %d : %ld %d %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13226 
13227  }
13228  else if(failure2){
13229  if(TRYCOLD){
13230  gammarel2=pow(1.0+10.0*NUMEPSILON,2.0);
13231  get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avcon,Avcov,&gammarel2,&delta,&numerator,&divisor,&Erf,urfconrel);
13232  }
13233  else{
13234  FTYPE gammarel2orig=gammarel2;
13235  // override
13236  gammarel2=1.0;
13237  FTYPE gammarel=1.0; // use this below
13238 
13239  // get new Erf(gammarel)
13240  get_m1closure_Erf(ptrgeom, Avcon, gammarel2, &Erf);
13241  if(Erf<ERADLIMIT) Erf=ERADLIMIT;
13242 
13243  SLOOPA(jj) urfconrel[jj] = 0.0;
13244 
13245  }
13246  if(1 || allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE2A;
13247  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE2A: normal gamma, but Erf<ERADLIMIT. ijk=%d %d %d : %ld %d %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13248  }
13249  else{
13250  if(TRYCOLD){
13251  gammarel2=gammamax*gammamax;
13252  get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avcon,Avcov,&gammarel2,&delta,&numerator,&divisor,&Erf,urfconrel);
13253  if(allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1B;
13254  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE1A: gammarel>gammamax (cold): gammarel2=%g Erf=%g : i=%d j=%d k=%d : %ld %d %g\n",gammarel2,Erf,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13255  }
13256  else{
13257  FTYPE gammarel2orig=gammarel2;
13258  FTYPE gammarel=gammamax;
13259  gammarel2=gammamax*gammamax;
13260 
13261  // get new Erf(gammarel)
13262  get_m1closure_Erf(ptrgeom, Avcon, gammarel2, &Erf);
13263 
13264 
13265  // Check if Erf is too small with gamma->gammamax
13266  if(Erf<ERADLIMIT){
13267  if(1 || allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1A;
13268  // Can't have Erf<0. Like floor on internal energy density. If leave Erf<0, then will drive code crazy with free energy.
13269  Erf=ERADLIMIT;
13270 
13271  // can't use normal velocity with small Erf -- fails with inf or nan
13272  SLOOPA(jj) urfconrel[jj] = 0.0;
13273 
13274  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE1A: gammarel>gammamax and Erf<ERADLIMIT: gammarel2=%g : i=%d j=%d k=%d : %ld %d %g\n",gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13275  }
13276  else{
13277  // if Erf normal, assume ok to have gammamax for radiation. This avoids fixups, which can generate more oscillations.
13278  // KORALTODO: But note that then check_on_inversion() won't know that failure and will check and report issue.
13279  if(allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1B;
13280  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE1B: gammarel>gammamax and Erf normal: gammarel2=%g : i=%d j=%d k=%d : %ld %d %g\n",gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13281 
13282  // regardless of Erf value, now that have some Erf, ensure gamma=gammamax
13283  // lab-frame radiation relative 4-velocity
13284  FTYPE alpha=ptrgeom->alphalapse;
13285  SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
13286 
13287  // compute \gammarel using this (gammatemp can be inf if Erf=ERADLIMIT, and then rescaling below will give urfconrel=0 and gammarel=1
13288  FTYPE gammatemp,qsqtemp;
13289  int gamma_calc_fromuconrel(FTYPE *uconrel, struct of_geom *geom, FTYPE*gamma, FTYPE *qsq);
13290  MYFUN(gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammatemp,&qsqtemp),"ucon_calc_rel4vel_fromuconrel: gamma_calc_fromuconrel failed\n","phys.tools.rad.c",1);
13291 
13292  if(!isfinite(gammatemp)){
13293  SLOOPA(jj) urfconrel[jj] =0.0;
13294  }
13295  else if(0&&gammatemp<=gammamax){
13296  // do nothing, don't make gamma larger just to get consistency
13297  }
13298  else{
13299  // now rescale urfconrel[i] so will give desired \gammamax
13300  SLOOPA(jj) urfconrel[jj] *= (gammamax/gammatemp);
13301  }
13302 
13303 #if(PRODUCTION==0)
13304  // check that gamma really correctly gammamax
13305  FTYPE gammatemp2,qsqtemp2;
13306  MYFUN(gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammatemp2,&qsqtemp2),"ucon_calc_rel4vel_fromuconrel: gamma_calc_fromuconrel failed\n","phys.tools.rad.c",1);
13307  if(showmessages) dualfprintf(fail_file,"CASE1B: gammarel>gammamax and Erf normal: gammarel2orig=%g gammamax=%g gammatemp=%g gammatemp2=%g ijk=%d %d %d : %ld %d %g\n",gammarel2orig,gammamax,gammatemp,gammatemp2,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13308 #endif
13309  }
13310  // if(showmessages && debugfail>=2) DLOOPA(jj) dualfprintf(fail_file,"CASE1B: urfconrel[%d]=%g uu[%d]=%g\n",jj,urfconrel[jj],jj,uu[URAD0+jj]);
13311 
13312  // SLOOPA(jj) urfconrel[jj] = 0.0; // consistent with gammarel2=1
13313  }
13314  }
13315 
13316 
13317  // if here, then one failure mode. See if optically thick or thin and reduce to (e.g.) fluid frame if thick
13318 
13319  // can't use normal velocity with small Erf -- fails with inf or nan
13320  // setup "old" pp in case used
13321  pp[PRAD0] = Erf;
13322  SLOOPA(jj) pp[PRAD1+jj-1] = urfconrel[jj];
13323 
13324 
13325 #if(0)
13326  // KORALTODO: Problems when tau<<1 and gamma->gammamax
13327  // KORALTODO: DUH, also should only do if failure, not if no failure.
13328  FTYPE tautot[NDIM],tautotmax;
13330  // then will possibly need tautotmax
13331  // get tautot based upon previous pp in order to determine what to do in case of failure
13332  calcfull_tautot(pp, ptrgeom, tautot, &tautotmax);
13333  }
13334 
13335 
13336  if(M1REDUCE==TOFLUIDFRAME && *lpflag<=UTOPRIMNOFAIL) SLOOPA(jj) urfconrel[jj]=pp[U1+jj-1];
13337  else if(M1REDUCE==TOZAMOFRAME) SLOOPA(jj) urfconrel[jj]=0.0;
13338  else if(M1REDUCE==TOOPACITYDEPENDENTFRAME) opacity_interpolated_urfconrel(tautotmax,pp,ptrgeom,Avcon,Erf,gammarel2,&Erf,urfconrel);
13339 #endif
13340 
13341  *Erfreturn=Erf; // pass back new Erf to pointer
13342  return(0);
13343 }
13344 
13345 
13346 
13347 
13349 static int get_m1closure_urfconrel(int showmessages, int allowlocalfailurefixandnoreport, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *Avcon, FTYPE *Avcov, FTYPE gammarel2, FTYPE delta, FTYPE numerator, FTYPE divisor, FTYPE *Erfreturn, FTYPE *urfconrel, PFTYPE *lpflag, PFTYPE *lpflagrad)
13350 {
13351  FTYPE Erf=*Erfreturn; // get initial Erf
13352  FTYPE gammamax=GAMMAMAXRAD;
13353  FTYPE gammamaxfail=GAMMAMAXRADFAIL;
13354  int jj,kk;
13355 
13356 
13358  //
13359  // Fix-up inversion if problem with gamma (i.e. velocity) or energy density in radiation rest-frame (i.e. Erf)
13360  //
13362 
13363  // NOTE: gammarel2 just below 1.0 already fixed to be =1.0
13364  // int nonfailure=gammarel2>=1.0 && gammarel2<=gammamax*gammamax/GAMMASMALLLIMIT/GAMMASMALLLIMIT;
13365  int nonfailure=gammarel2>=1.0L && Erf>ERADLIMIT && gammarel2<=gammamax*gammamax/GAMMASMALLLIMIT/GAMMASMALLLIMIT;
13366  // falilure1 : gammarel2 normal, but already Erf<ERADLIMIT (note for M1 that gammarel2>=1/4 for any reasonable chance for correct non-zero Erf
13367  int failure1=Avcon[0]<0.0 || (gammarel2>0.0 && gammarel2<=0.25L && delta>=0.0 && divisor!=0.0) || numerator==0.0 || gammarel2>=1.0 && delta>=0.0 && divisor!=0.0 && Erf<ERADLIMIT;
13368  // gamma probably around 1
13369  int failure2=gammarel2<1.0 && gammarel2>0.0 && delta>=0.0;
13370  // i.e. all else, so not really used below.
13371  int failure3=gammarel2>gammamax*gammamax && Erf>=ERADLIMIT || gammarel2<0.0 || delta<0. || divisor==0.0 && numerator==0.0 || divisor==0.0 && numerator!=0.0;
13372 
13373  // any failure
13374  int failure=!nonfailure || !isfinite(gammarel2) || !isfinite(Erf);
13375 
13376  if(failure && (failure1==0 && failure2==0 && failure3==0)){
13377  if(debugfail>=2) dualfprintf(fail_file,"Undetected failure, now considered\n");
13378  }
13379 
13380 
13381  FTYPE Erf0=MAX(NUMEPSILON*fabs(Avcon[TT])/gammamax/gammamax,ERADLIMIT);
13382  if(nonfailure){
13383  // get good relative velocity
13384  FTYPE gammarel=sqrt(gammarel2);
13385  FTYPE alpha=ptrgeom->alphalapse;
13386 
13387  SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
13388 
13389 #if(0)
13390  // if(Erf<ERADLIMIT) Erf=ERADLIMIT; // case when velocity fine and probably just Erf slightly negative
13391  // if(Erf<ERADLIMIT) Erf=MAX(NUMEPSILON*fabs(Erf),ERADLIMIT); // case when velocity fine and probably just Erf slightly negative
13392  if(Erf<ERADLIMIT) Erf=Erf0; // case when velocity fine and probably just Erf slightly negative
13393 #endif
13394 
13395  *Erfreturn=Erf; // pass back new Erf to pointer
13396  return(0);
13397 
13398  // dualfprintf(fail_file,"NO failure: %g %g ijk=%d %d %d\n",Erf,gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13399  }
13400  else{
13401  FTYPE Avconorig[NDIM],Avcovorig[NDIM];
13402  DLOOPA(jj){
13403  Avconorig[jj]=Avcon[jj];
13404  Avcovorig[jj]=Avcov[jj];
13405  }
13406  FTYPE gammarel2orig;
13407  gammarel2orig=gammarel2;
13408  FTYPE Erforig;
13409  Erforig=Erf;
13410 
13411  // get \gammarel=1 case
13412  FTYPE gammarel2slow=pow(1.0+10.0*NUMEPSILON,2.0);
13413  FTYPE Avconslow[NDIM],Avcovslow[NDIM],Erfslow,urfconrelslow[NDIM];
13414  DLOOPA(jj){
13415  Avconslow[jj]=Avcon[jj];
13416  Avcovslow[jj]=Avcov[jj];
13417  }
13418  Erfslow=Erf;
13419  get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avconslow,Avcovslow,&gammarel2slow,&delta,&numerator,&divisor,&Erfslow,urfconrelslow);
13420 
13421  // get \gammarel=gammamax case
13422  FTYPE gammarel2fast=gammamax*gammamax;
13423  FTYPE Avconfast[NDIM],Avcovfast[NDIM],Erffast,urfconrelfast[NDIM];
13424  DLOOPA(jj){
13425  Avconfast[jj]=Avcon[jj];
13426  Avcovfast[jj]=Avcov[jj];
13427  }
13428  Erffast=Erf;
13429  get_m1closure_gammarel2_cold(showmessages,ptrgeom,Avconfast,Avcovfast,&gammarel2fast,&delta,&numerator,&divisor,&Erffast,urfconrelfast);
13430 
13431  // dualfprintf(fail_file,"JONVSOLEK: Avconorig: %g %g %g %g\n",Avcon[0],Avcon[1],Avcon[2],Avcon[3]);
13432 
13433  int usingfast=1;
13434  // choose by which Avcov[0] is closest to original
13435  if( fabs(Avconslow[0]-Avcon[0])>fabs(Avconfast[0]-Avcon[0]) ){ // compare Avcon that has positive sign always
13436  usingfast=1;
13437  Erf=Erffast;
13438  gammarel2=gammarel2fast;
13439  DLOOPA(jj){
13440  Avcon[jj]=Avconfast[jj];
13441  Avcov[jj]=Avcovfast[jj];
13442  urfconrel[jj]=urfconrelfast[jj];
13443  }
13444  }
13445  else{
13446  usingfast=0;
13447  Erf=Erfslow;
13448  gammarel2=gammarel2slow;
13449  DLOOPA(jj){
13450  Avcon[jj]=Avconslow[jj];
13451  Avcov[jj]=Avcovslow[jj];
13452  urfconrel[jj]=urfconrelslow[jj];
13453  }
13454  }
13455 
13456  // catch bad issue for when using fast or slow will be bad because probably momentum is bad if inverted energy
13457  if(Avcovorig[TT]>0.0){
13458  SLOOPA(jj) urfconrel[jj]=0.0;
13459  //dualfprintf(fail_file,"THIS ONE1\n");
13460  }
13461  else if(Avcov[TT]>0.0){
13462  // Erf=ERADLIMIT;
13463  Erf=Erf0;
13464  SLOOPA(jj) urfconrel[jj]=0.0;
13465  //dualfprintf(fail_file,"THIS ONE2\n");
13466  }
13467  else{
13468  // Erf=ERADLIMIT;
13469  // Erf=MAX(MIN(Erf,Erforig),ERADLIMIT);
13470  if(gammarel2orig>=1.0 && isfinite(gammarel2orig) && isfinite(Erforig)){
13471  Erf=MAX(MIN(Erf,Erforig),Erf0);
13472  // Erf=ERADLIMIT;
13473  // dualfprintf(fail_file,"THIS ONE3\n");
13474  }
13475 #define AVCOVRELDIFFALLOWED 1E-2 // KORALTODO: only use new "cold" solution if relatively close Avcov.
13476  else if(fabs(Avcovorig[TT]-Avcov[TT])/fabs(fabs(Avcovorig[TT])+fabs(Avcov[TT]))<AVCOVRELDIFFALLOWED ){
13477  //dualfprintf(fail_file,"THIS ONE4\n");
13478  Erf=MAX(MIN(Erf,Erf*(-Avcovorig[TT])/(ERADLIMIT+fabs(-Avcov[TT]))),Erf0);
13479  Erf=MAX(MIN(Erf,Erf*(-Avcov[TT])/(ERADLIMIT+fabs(-Avcovorig[TT]))),Erf0);
13480  //dualfprintf(fail_file,"nstep=%ld steppart=%d ijk=%d %d %d : Erforig=%g Erf=%g urfconrel=%g %g %g : Avcovorig=%g Avcov=%g\n",nstep,steppart,ptrgeom->i,ptrgeom->j,ptrgeom->k,Erforig,Erf,urfconrel[1],urfconrel[2],urfconrel[3],Avcovorig[0],Avcov[0]);
13481  // Erf=6E-15;
13482  }
13483  else{
13484  //dualfprintf(fail_file,"THIS ONE5\n");
13485  Erf=Erf0;
13486  }
13487 #if(0)
13488  // for RADBEAM2DKSVERT, very tricky and very sensitive (i.e. whether really fails) at coordinate singularity.
13489  // if(gammarel2orig<1.0){
13490  // if(gammarel2orig<0.5){
13491  if(gammarel2orig<=0.0){
13492  dualfprintf(fail_file,"THIS ONE6\n");
13493  Erf=Erf0;
13494  // Erf=ERADLIMIT;
13495  }
13496 #endif
13497  }
13498 
13499  // dualfprintf(fail_file,"JONVSOLEK: usingfast=%d Avconfast: %g %g %g %g : Avconslow: %g %g %g %g : Erffast=%g Erfslow=%g urfconfast=%g %g %g urfconslow=%g %g %g\n",usingfast,Avconfast[0],Avconfast[1],Avconfast[2],Avconfast[3],Avconslow[0],Avconslow[1],Avconslow[2],Avconslow[3],Erffast,Erfslow,urfconrelfast[1],urfconrelfast[2],urfconrelfast[3],urfconrelslow[1],urfconrelslow[2],urfconrelslow[3]);
13500 
13501 
13502  // report
13503  if(1||allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1A;
13504  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASEGEN: gammarel>gammamax (cold, usingfast=%d): gammarel2=%g Erf=%g : i=%d j=%d k=%d : %ld %d %g\n",usingfast,gammarel2,Erf,ptrgeom->i,ptrgeom->j,ptrgeom->k,nstep,steppart,t);
13505  }
13506 
13507 
13508  // if here, then one failure mode. See if optically thick or thin and reduce to (e.g.) fluid frame if thick
13509 
13510  // can't use normal velocity with small Erf -- fails with inf or nan
13511  // setup "old" pp in case used
13512  pp[PRAD0] = Erf;
13513  SLOOPA(jj) pp[PRAD1+jj-1] = urfconrel[jj];
13514 
13515 
13516 #if(0)
13517  // normally don't ever do this unless really debugging inversion.
13518  // if((ptrgeom->j==14 || ptrgeom->j==13 || ptrgeom->j==15) &&nstep>=195){// || *lpflagrad!=0 && debugfail>=2){
13519  if(nstep>=223){
13520  // if(0&&nstep>=223){// || *lpflagrad!=0 && debugfail>=2){
13521  // first report info so can check on inversion
13522  static long long int failnum=0;
13523  FTYPE fakedt=0.0; // since no 4-force
13524  FTYPE fakeCUf[NUMDTCUFS]={0}; // fake
13525  FTYPE fakeCUimp[1]={0}; // fake
13526  FTYPE dUother[NPR]={0};// fake
13527  struct of_state *qptr=NULL; // fake
13528  failnum++;
13529  globalpin[ENTROPY]=0.0;
13530  globaluu[ENTROPY]=0.0;
13531  pp[ENTROPY]=0.0;
13532 
13533  globalpin[PRAD0] = Erf;
13534  SLOOPA(jj) globalpin[PRAD1+jj-1] = urfconrel[jj];
13535 
13536  // ppfirst is faked as pp
13537  mathematica_report_check(0, 3, failnum, *lpflagrad, BIG, -1, -1, fakedt, ptrgeom, pp, pp, pp, globalpin, globalpin, globalpin, globaluu, globaluu, globaluu, globaluu, fakeCUf, fakeCUimp, qptr, dUother);
13538  }
13539  // if(nstep==224) exit(0);
13540 #endif
13541 
13542 #if(0)
13543  // KORALTODO: Problems when tau<<1 and gamma->gammamax
13544  FTYPE tautot[NDIM],tautotmax;
13546  // then will possibly need tautotmax
13547  // get tautot based upon previous pp in order to determine what to do in case of failure
13548  calcfull_tautot(pp, ptrgeom, tautot, &tautotmax);
13549  }
13550 
13551 
13552  if(M1REDUCE==TOFLUIDFRAME && *lpflag<=UTOPRIMNOFAIL) SLOOPA(jj) urfconrel[jj]=pp[U1+jj-1];
13553  else if(M1REDUCE==TOZAMOFRAME) SLOOPA(jj) urfconrel[jj]=0.0;
13554  else if(M1REDUCE==TOOPACITYDEPENDENTFRAME) opacity_interpolated_urfconrel(tautotmax,pp,ptrgeom,Avcon,Erf,gammarel2,&Erf,urfconrel);
13555 #endif
13556 
13557  *Erfreturn=Erf; // pass back new Erf to pointer
13558 
13559 
13560  // catch any nan/inf's:
13561  int notfinite=(!isfinite(Erf) || !isfinite(urfconrel[1])|| !isfinite(urfconrel[2])|| !isfinite(urfconrel[3]));
13562  if(notfinite){
13563  // nothing else to do unless want to use nan/inf as indicator that should abort something
13564  // using such a small Erf can lead itself to problems due to precision issues, so assume will fixup this
13565  Erf=ERADLIMIT;
13566  SLOOPA(jj) urfconrel[jj]=0.0; // ZAMO
13567  if(1||allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1B;
13568  }
13569 
13570 
13571 
13572  // DEBUG:
13573  if(debugfail>=2){
13574  if(notfinite){
13575  dualfprintf(fail_file,"JONNAN: ijk=%d %d %d : %g %g : %g %g %g : %d %d %d %d : %g %g %g %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,Erf,gammarel2,urfconrel[1],urfconrel[2],urfconrel[3],failure1,failure2,failure3,failure,Avcon[0],Avcon[1],Avcon[2],Avcon[3]);
13576  }
13577  }
13578 
13579 
13580  return(0);
13581 }
13582 
13583 
13584 
13585 
13587 static int get_m1closure_urfconrel_olek(int showmessages, int allowlocalfailurefixandnoreport, struct of_geom *ptrgeom, FTYPE *pp, FTYPE *Avcon, FTYPE *Avcov, FTYPE gammarel2, FTYPE delta, FTYPE *Erfreturn, FTYPE *urfconrel, PFTYPE *lpflag, PFTYPE *lpflagrad)
13588 {
13589  FTYPE Erf=*Erfreturn; // get initial Erf
13590  FTYPE gammamax=GAMMAMAXRAD;
13591  FTYPE gammamaxfail=GAMMAMAXRADFAIL;
13592  int jj,kk;
13593 
13594 
13596  //
13597  // Fix-up inversion if problem with gamma (i.e. velocity) or energy density in radiation rest-frame (i.e. Erf)
13598  //
13600 
13601  int failure1=gammarel2>1.01*gammamax*gammamax || gammarel2<0. || delta<0.;
13602  int failure2=gammarel2<1. || delta<0. || !isfinite(gammarel2); // NOTE: first failure1 already catches delta<0.
13603 
13604 
13605 
13606  if(failure1){
13607  // if(failure1 && tautotmax<TAUFAILLIMIT){ // works for DBLSHADOW
13608 
13609  FTYPE gammarel=gammamax;
13610  gammarel2=gammamax*gammamax;
13611 
13612  // get new Erf(gammarel)
13613  get_m1closure_Erf(ptrgeom, Avcon, gammarel2, &Erf);
13614 
13615 
13616  // Check if Erf is too small with gamma->gammamax
13617  if(Erf<ERADLIMIT || !isfinite(Erf)){
13618  if(1 || allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1A;
13619  // Can't have Erf<0. Like floor on internal energy density. If leave Erf<0, then will drive code crazy with free energy.
13620  Erf=ERADLIMIT;
13621 
13622  // can't use normal velocity with small Erf -- fails with inf or nan
13623  SLOOPA(jj) urfconrel[jj] = 0.0;
13624 
13625  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE1A: gammarel>gammamax and Erf<ERADLIMIT: gammarel2=%g : i=%d j=%d k=%d\n",gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13626  }
13627  else{
13628  // if Erf normal, assume ok to have gammamax for radiation. This avoids fixups, which can generate more oscillations.
13629  if(allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE1B;
13630  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE1B: gammarel>gammamax and Erf normal: gammarel2=%g : i=%d j=%d k=%d\n",gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13631 
13632  // regardless of Erf value, now that have some Erf, ensure gamma=gammamax
13633  // lab-frame radiation relative 4-velocity
13634  FTYPE alpha=ptrgeom->alphalapse;
13635  SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
13636 
13637  // compute \gammarel using this (gammatemp can be inf if Erf=ERADLIMIT, and then rescaling below will give urfconrel=0 and gammarel=1
13638  FTYPE gammatemp,qsqtemp;
13639  int gamma_calc_fromuconrel(FTYPE *uconrel, struct of_geom *geom, FTYPE*gamma, FTYPE *qsq);
13640  MYFUN(gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammatemp,&qsqtemp),"ucon_calc_rel4vel_fromuconrel: gamma_calc_fromuconrel failed\n","phys.tools.rad.c",1);
13641 
13642  // now rescale urfconrel[i] so will give desired \gammamax
13643  SLOOPA(jj) urfconrel[jj] *= (gammamax/gammatemp);
13644 
13645 #if(PRODUCTION==0)
13646  // check that gamma really correctly gammamax
13647  FTYPE gammatemp2,qsqtemp2;
13648  MYFUN(gamma_calc_fromuconrel(urfconrel,ptrgeom,&gammatemp2,&qsqtemp2),"ucon_calc_rel4vel_fromuconrel: gamma_calc_fromuconrel failed\n","phys.tools.rad.c",1);
13649  if(showmessages) dualfprintf(fail_file,"CASE1B: gammarel>gammamax and Erf normal: gammamax=%g gammatemp=%g gammatemp2=%g ijk=%d %d %d\n",gammamax,gammatemp,gammatemp2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13650 #endif
13651  }
13652 
13653  }
13655  //
13656  // Second case is if gammarel<1 or delta<0, then set gammarel=1. If Erf<ERADLIMIT (~0), then set Erf=ERADLIMIT and gammarel=1.
13657  // Can't assume this condition is equivalent to large gamma, because if not, then leads to crazy boost of energy.
13658  //
13660  else if(failure2){
13661 
13662 
13663  FTYPE gammarel2orig=gammarel2;
13664  // override
13665  gammarel2=1.0;
13666  FTYPE gammarel=1.0; // use this below
13667 
13668  // get new Erf(gammarel)
13669  get_m1closure_Erf(ptrgeom, Avcon, gammarel2, &Erf);
13670  SLOOPA(jj) urfconrel[jj] = 0.0;
13671 
13672 
13673  if(Erf<ERADLIMIT || !isfinite(Erf)){ // JCM
13674  // Can't have Erf<0. Like floor on internal energy density. If leave Erf<0, then will drive code crazy with free energy.
13675  Erf=ERADLIMIT;
13676  if(1 || allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE2A;
13677  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE2A: gamma<1 or delta<0 and Erf<ERADLIMIT : gammarel2=%g : i=%d j=%d k=%d\n",gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13678  }
13679  else{
13680  // normal Erf
13681  if(1 || allowlocalfailurefixandnoreport==0) *lpflagrad=UTOPRIMRADFAILCASE2B;
13682  if(showmessages && debugfail>=2) dualfprintf(fail_file,"CASE2B: gamma<1 or delta<0 and Erf normal : gammamax=%g gammarel2orig=%21.15g gammarel2=%21.15g delta=%g : i=%d j=%d k=%d\n",gammamax,gammarel2orig,gammarel2,delta,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13683  }
13684 
13685 
13686 
13687  }
13689  //
13690  // Third case is if no bad conditions, then try regular calculation. If Erf<ERADLIMIT, then already caught with first condition
13691  //
13693  else{
13694 
13695  if(Erf<ERADLIMIT || !isfinite(Erf)){
13696  Erf=ERADLIMIT;
13697  SLOOPA(jj) urfconrel[jj] = 0.0;
13698  // must use above because if use ERADLIMIT in normal urfconrel, then urfconrel will be HUGE and probably give inf or nan due to Avcon/(Erf*gammarel) term.
13699  }
13700  else{
13701  // get good relative velocity
13702  FTYPE gammarel=sqrt(gammarel2);
13703  FTYPE alpha=ptrgeom->alphalapse;
13704 
13705  // NOTEMARK: This overwrites choice above for urfconrel when Erf<ERADLIMIT.
13706  SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
13707  }
13708 
13709 
13710  // dualfprintf(fail_file,"NO failure: %g %g ijk=%d %d %d\n",Erf,gammarel2,ptrgeom->i,ptrgeom->j,ptrgeom->k);
13711  }
13712 
13713 
13714  if(debugfail>=2){
13715  if(!isfinite(Erf) || !isfinite(gammarel2) || !isfinite(urfconrel[0])|| !isfinite(urfconrel[1])|| !isfinite(urfconrel[2])|| !isfinite(urfconrel[3]) ){
13716  dualfprintf(fail_file,"OLEKNAN: ijk=%d %d %d : %g %g : %g %g %g : %d %d : %g %g %g %g\n",ptrgeom->i,ptrgeom->j,ptrgeom->k,Erf,gammarel2,urfconrel[1],urfconrel[2],urfconrel[3],failure1,failure2,Avcon[0],Avcon[1],Avcon[2],Avcon[3]);
13717  }
13718  }
13719 
13720  *Erfreturn=Erf; // pass back new Erf to pointer
13721  return(0);
13722 }
13723 
13724 
13725 
13726 
13727 
13728 
13729 
13730 
13732 static int get_m1closure_gammarel2_cold_old(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn, FTYPE *Erfreturn, FTYPE *urfconrel)
13733 {
13734  FTYPE gamma2,gammarel2,delta;
13735  FTYPE Erf;
13736  FTYPE alpha=ptrgeom->alphalapse;
13737  int jj;
13738 
13739  static FTYPE gctt, gv11, gv12, gv13, gv14, gv22, gv23, gv24, gv33, gv34, gv44, Rtt, Rtx, Rty, Rtz;
13740  gv11=ptrgeom->gcov[GIND(0,0)];
13741  gv12=ptrgeom->gcov[GIND(0,1)];
13742  gv13=ptrgeom->gcov[GIND(0,2)];
13743  gv14=ptrgeom->gcov[GIND(0,3)];
13744  gv22=ptrgeom->gcov[GIND(1,1)];
13745  gv23=ptrgeom->gcov[GIND(1,2)];
13746  gv24=ptrgeom->gcov[GIND(1,3)];
13747  gv33=ptrgeom->gcov[GIND(2,2)];
13748  gv34=ptrgeom->gcov[GIND(2,3)];
13749  gv44=ptrgeom->gcov[GIND(3,3)];
13750  FTYPE Rttold=Avcon[0];
13751  Rtx=Avcon[1];
13752  Rty=Avcon[2];
13753  Rtz=Avcon[3];
13754  gctt=ptrgeom->gcon[GIND(0,0)];
13755 
13756 
13757  // choose gamma
13758  if(gammarel2return==NULL){
13759  FTYPE gammamaxfail=GAMMAMAXRADFAIL;
13760  FTYPE gammamax=GAMMAMAXRAD;
13761  gammarel2=gammamax*gammamax;
13762  }
13763  else gammarel2=*gammarel2return; // feed in desired gammarel2
13764 
13765  FTYPE utsq=gammarel2/(alpha*alpha);
13766 
13767 
13768 
13769  // but check if utsq is too small
13770  FTYPE utsqmina=(0.5*(-8.*gctt*Power(gv12,2)*Power(Rtx,2) + 8.*gv22*Power(Rtx,2) +
13771  8.*gctt*gv11*gv22*Power(Rtx,2) - 16.*gctt*gv12*gv13*Rtx*Rty +
13772  16.*gv23*Rtx*Rty + 16.*gctt*gv11*gv23*Rtx*Rty -
13773  8.*gctt*Power(gv13,2)*Power(Rty,2) + 8.*gv33*Power(Rty,2) +
13774  8.*gctt*gv11*gv33*Power(Rty,2) - 16.*gctt*gv12*gv14*Rtx*Rtz +
13775  16.*gv24*Rtx*Rtz + 16.*gctt*gv11*gv24*Rtx*Rtz -
13776  16.*gctt*gv13*gv14*Rty*Rtz + 16.*gv34*Rty*Rtz +
13777  16.*gctt*gv11*gv34*Rty*Rtz - 8.*gctt*Power(gv14,2)*Power(Rtz,2) +
13778  8.*gv44*Power(Rtz,2) + 8.*gctt*gv11*gv44*Power(Rtz,2) -
13779  1.*Sqrt(Power(8.*gctt*Power(gv12,2)*Power(Rtx,2) - 8.*gv22*Power(Rtx,2) -
13780  8.*gctt*gv11*gv22*Power(Rtx,2) + 16.*gctt*gv12*gv13*Rtx*Rty -
13781  16.*gv23*Rtx*Rty - 16.*gctt*gv11*gv23*Rtx*Rty +
13782  8.*gctt*Power(gv13,2)*Power(Rty,2) - 8.*gv33*Power(Rty,2) -
13783  8.*gctt*gv11*gv33*Power(Rty,2) + 16.*gctt*gv12*gv14*Rtx*Rtz -
13784  16.*gv24*Rtx*Rtz - 16.*gctt*gv11*gv24*Rtx*Rtz +
13785  16.*gctt*gv13*gv14*Rty*Rtz - 16.*gv34*Rty*Rtz -
13786  16.*gctt*gv11*gv34*Rty*Rtz + 8.*gctt*Power(gv14,2)*Power(Rtz,2) -
13787  8.*gv44*Power(Rtz,2) - 8.*gctt*gv11*gv44*Power(Rtz,2),2) -
13788  4.*(16.*Power(gv12,2)*Power(Rtx,2) - 16.*gv11*gv22*Power(Rtx,2) +
13789  32.*gv12*gv13*Rtx*Rty - 32.*gv11*gv23*Rtx*Rty +
13790  16.*Power(gv13,2)*Power(Rty,2) - 16.*gv11*gv33*Power(Rty,2) +
13791  32.*gv12*gv14*Rtx*Rtz - 32.*gv11*gv24*Rtx*Rtz +
13792  32.*gv13*gv14*Rty*Rtz - 32.*gv11*gv34*Rty*Rtz +
13793  16.*Power(gv14,2)*Power(Rtz,2) - 16.*gv11*gv44*Power(Rtz,2))*
13794  (Power(gctt,2)*Power(gv12,2)*Power(Rtx,2) + gctt*gv22*Power(Rtx,2) -
13795  1.*Power(gctt,2)*gv11*gv22*Power(Rtx,2) +
13796  2.*Power(gctt,2)*gv12*gv13*Rtx*Rty + 2.*gctt*gv23*Rtx*Rty -
13797  2.*Power(gctt,2)*gv11*gv23*Rtx*Rty +
13798  Power(gctt,2)*Power(gv13,2)*Power(Rty,2) + gctt*gv33*Power(Rty,2) -
13799  1.*Power(gctt,2)*gv11*gv33*Power(Rty,2) +
13800  2.*Power(gctt,2)*gv12*gv14*Rtx*Rtz + 2.*gctt*gv24*Rtx*Rtz -
13801  2.*Power(gctt,2)*gv11*gv24*Rtx*Rtz +
13802  2.*Power(gctt,2)*gv13*gv14*Rty*Rtz + 2.*gctt*gv34*Rty*Rtz -
13803  2.*Power(gctt,2)*gv11*gv34*Rty*Rtz +
13804  Power(gctt,2)*Power(gv14,2)*Power(Rtz,2) + gctt*gv44*Power(Rtz,2) -
13805  1.*Power(gctt,2)*gv11*gv44*Power(Rtz,2)))))/
13806  (16.*Power(gv12,2)*Power(Rtx,2) - 16.*gv11*gv22*Power(Rtx,2) +
13807  32.*gv12*gv13*Rtx*Rty - 32.*gv11*gv23*Rtx*Rty +
13808  16.*Power(gv13,2)*Power(Rty,2) - 16.*gv11*gv33*Power(Rty,2) +
13809  32.*gv12*gv14*Rtx*Rtz - 32.*gv11*gv24*Rtx*Rtz + 32.*gv13*gv14*Rty*Rtz -
13810  32.*gv11*gv34*Rty*Rtz + 16.*Power(gv14,2)*Power(Rtz,2) -
13811  16.*gv11*gv44*Power(Rtz,2));
13812 
13813  FTYPE utsqminb=(0.5*(-8.*gctt*Power(gv12,2)*Power(Rtx,2) + 8.*gv22*Power(Rtx,2) +
13814  8.*gctt*gv11*gv22*Power(Rtx,2) - 16.*gctt*gv12*gv13*Rtx*Rty +
13815  16.*gv23*Rtx*Rty + 16.*gctt*gv11*gv23*Rtx*Rty -
13816  8.*gctt*Power(gv13,2)*Power(Rty,2) + 8.*gv33*Power(Rty,2) +
13817  8.*gctt*gv11*gv33*Power(Rty,2) - 16.*gctt*gv12*gv14*Rtx*Rtz +
13818  16.*gv24*Rtx*Rtz + 16.*gctt*gv11*gv24*Rtx*Rtz -
13819  16.*gctt*gv13*gv14*Rty*Rtz + 16.*gv34*Rty*Rtz +
13820  16.*gctt*gv11*gv34*Rty*Rtz - 8.*gctt*Power(gv14,2)*Power(Rtz,2) +
13821  8.*gv44*Power(Rtz,2) + 8.*gctt*gv11*gv44*Power(Rtz,2) +
13822  Sqrt(Power(8.*gctt*Power(gv12,2)*Power(Rtx,2) - 8.*gv22*Power(Rtx,2) -
13823  8.*gctt*gv11*gv22*Power(Rtx,2) + 16.*gctt*gv12*gv13*Rtx*Rty -
13824  16.*gv23*Rtx*Rty - 16.*gctt*gv11*gv23*Rtx*Rty +
13825  8.*gctt*Power(gv13,2)*Power(Rty,2) - 8.*gv33*Power(Rty,2) -
13826  8.*gctt*gv11*gv33*Power(Rty,2) + 16.*gctt*gv12*gv14*Rtx*Rtz -
13827  16.*gv24*Rtx*Rtz - 16.*gctt*gv11*gv24*Rtx*Rtz +
13828  16.*gctt*gv13*gv14*Rty*Rtz - 16.*gv34*Rty*Rtz -
13829  16.*gctt*gv11*gv34*Rty*Rtz + 8.*gctt*Power(gv14,2)*Power(Rtz,2) -
13830  8.*gv44*Power(Rtz,2) - 8.*gctt*gv11*gv44*Power(Rtz,2),2) -
13831  4.*(16.*Power(gv12,2)*Power(Rtx,2) - 16.*gv11*gv22*Power(Rtx,2) +
13832  32.*gv12*gv13*Rtx*Rty - 32.*gv11*gv23*Rtx*Rty +
13833  16.*Power(gv13,2)*Power(Rty,2) - 16.*gv11*gv33*Power(Rty,2) +
13834  32.*gv12*gv14*Rtx*Rtz - 32.*gv11*gv24*Rtx*Rtz +
13835  32.*gv13*gv14*Rty*Rtz - 32.*gv11*gv34*Rty*Rtz +
13836  16.*Power(gv14,2)*Power(Rtz,2) - 16.*gv11*gv44*Power(Rtz,2))*
13837  (Power(gctt,2)*Power(gv12,2)*Power(Rtx,2) + gctt*gv22*Power(Rtx,2) -
13838  1.*Power(gctt,2)*gv11*gv22*Power(Rtx,2) +
13839  2.*Power(gctt,2)*gv12*gv13*Rtx*Rty + 2.*gctt*gv23*Rtx*Rty -
13840  2.*Power(gctt,2)*gv11*gv23*Rtx*Rty +
13841  Power(gctt,2)*Power(gv13,2)*Power(Rty,2) + gctt*gv33*Power(Rty,2) -
13842  1.*Power(gctt,2)*gv11*gv33*Power(Rty,2) +
13843  2.*Power(gctt,2)*gv12*gv14*Rtx*Rtz + 2.*gctt*gv24*Rtx*Rtz -
13844  2.*Power(gctt,2)*gv11*gv24*Rtx*Rtz +
13845  2.*Power(gctt,2)*gv13*gv14*Rty*Rtz + 2.*gctt*gv34*Rty*Rtz -
13846  2.*Power(gctt,2)*gv11*gv34*Rty*Rtz +
13847  Power(gctt,2)*Power(gv14,2)*Power(Rtz,2) + gctt*gv44*Power(Rtz,2) -
13848  1.*Power(gctt,2)*gv11*gv44*Power(Rtz,2)))))/
13849  (16.*Power(gv12,2)*Power(Rtx,2) - 16.*gv11*gv22*Power(Rtx,2) +
13850  32.*gv12*gv13*Rtx*Rty - 32.*gv11*gv23*Rtx*Rty +
13851  16.*Power(gv13,2)*Power(Rty,2) - 16.*gv11*gv33*Power(Rty,2) +
13852  32.*gv12*gv14*Rtx*Rtz - 32.*gv11*gv24*Rtx*Rtz + 32.*gv13*gv14*Rty*Rtz -
13853  32.*gv11*gv34*Rty*Rtz + 16.*Power(gv14,2)*Power(Rtz,2) -
13854  16.*gv11*gv44*Power(Rtz,2));
13855 
13856  dualfprintf(fail_file,"utsq=%g utsqmina=%g utsqminb=%g\n",utsq,utsqmina,utsqminb);
13857  // KORALTODO: override (only applicable for first root) Unsure if 2nd root used for GR in ergosphere. e.g. gv11 switches sign!
13858  if(utsq<utsqmina && utsqmina>utsqminb) utsq=utsqmina;
13859  if(utsq<utsqminb && utsqminb>utsqmina) utsq=utsqminb;
13860 
13861 
13862  FTYPE Avcovorig[NDIM];
13863  DLOOPA(jj) Avcovorig[jj]=Avcov[jj];
13864 
13865 
13866  // get new Avcon[0]=R^{tt}
13867 
13868  Avcon[0]=(-1.*(gctt + 4.*utsq)*(gctt*(gv12*Rtx + gv13*Rty + gv14*Rtz) + 4.*(gv12*Rtx + gv13*Rty + gv14*Rtz)*utsq +
13869  0.16666666666666666*Sqrt(36.*Power(gv12*Rtx + gv13*Rty + gv14*Rtz,2)*Power(gctt + 4.*utsq,2) -
13870  36.*(gv22*Power(Rtx,2) + 2.*gv23*Rtx*Rty + gv33*Power(Rty,2) + 2.*gv24*Rtx*Rtz + 2.*gv34*Rty*Rtz + gv44*Power(Rtz,2))*
13871  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq)))))/
13872  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq));
13873 
13874  Erf=(-3.*(gctt*(gv12*Rtx + gv13*Rty + gv14*Rtz) + 4.*(gv12*Rtx + gv13*Rty + gv14*Rtz)*utsq +
13875  0.16666666666666666*Sqrt(36.*Power(gv12*Rtx + gv13*Rty + gv14*Rtz,2)*Power(gctt + 4.*utsq,2) -
13876  36.*(gv22*Power(Rtx,2) + 2.*gv23*Rtx*Rty + gv33*Power(Rty,2) + 2.*gv24*Rtx*Rtz + 2.*gv34*Rty*Rtz + gv44*Power(Rtz,2))*
13877  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq)))))/
13878  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq));
13879 
13880 
13881  dualfprintf(fail_file,"NOR SOL: Avcon0new=%g Avcon0old=%g Erf=%g :: %g %g %g\n",Avcon[0],Rttold,Erf,Rtx,Rty,Rtz);
13882 
13883  FTYPE Avcovnew[NDIM];
13884  indices_21(Avcon,Avcovnew,ptrgeom);
13885  DLOOPA(jj) dualfprintf(fail_file,"jj=%d Avcovorig=%g Avcovnew=%g\n",jj,Avcovorig[jj],Avcovnew[jj]);
13886 
13887 
13888  delta=0; // not yet
13889 
13890  if(1){
13891  // alt solution
13892  FTYPE Avalt=(-1.*(gctt + 4.*utsq)*(gctt*(gv12*Rtx + gv13*Rty + gv14*Rtz) + 4.*(gv12*Rtx + gv13*Rty + gv14*Rtz)*utsq -
13893  0.16666666666666666*Sqrt(36.*Power(gv12*Rtx + gv13*Rty + gv14*Rtz,2)*Power(gctt + 4.*utsq,2) -
13894  36.*(gv22*Power(Rtx,2) + 2.*gv23*Rtx*Rty + gv33*Power(Rty,2) + 2.*gv24*Rtx*Rtz + 2.*gv34*Rty*Rtz + gv44*Power(Rtz,2))*
13895  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq)))))/
13896  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq));
13897 
13898 
13899  FTYPE Erfalt=(-3.*gctt*(gv12*Rtx + gv13*Rty + gv14*Rtz) - 12.*(gv12*Rtx + gv13*Rty + gv14*Rtz)*utsq +
13900  0.5*Sqrt(36.*Power(gv12*Rtx + gv13*Rty + gv14*Rtz,2)*Power(gctt + 4.*utsq,2) -
13901  36.*(gv22*Power(Rtx,2) + 2.*gv23*Rtx*Rty + gv33*Power(Rty,2) + 2.*gv24*Rtx*Rtz + 2.*gv34*Rty*Rtz + gv44*Power(Rtz,2))*
13902  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq))))/
13903  (Power(gctt,2)*gv11 + 8.*utsq*(1. + 2.*gv11*utsq) + gctt*(-1. + 8.*gv11*utsq));
13904 
13905  dualfprintf(fail_file,"ALT SOL: Avalt=%g Av0old=%g Erfalt=%g : %g %g %g\n",Avalt,Rttold,Erfalt,Rtx,Rty,Rtz);
13906  }
13907 
13908 
13909  *gammarel2return=gammarel2;
13910  *deltareturn=delta;
13911 
13912  // get good relative velocity
13913  FTYPE gammarel=sqrt(gammarel2);
13914 
13915  // get relative 4-velocity
13916  if(Erf>0.0) SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
13917  else SLOOPA(jj) urfconrel[jj] = 0.0;
13918 
13919  dualfprintf(fail_file,"NORM ROOT 4-vel: %g %g %g : %g\n",urfconrel[1],urfconrel[2],urfconrel[3],ptrgeom->gdet);
13920 
13921 
13922  *Erfreturn=Erf; // pass back new Erf to pointer
13923 
13924 
13925  return(0);
13926 }
13927 
13928 
13929 
13930 
13931 
13932 
13933 
13934 
13935 
13936 
13937 
13939 static int get_m1closure_gammarel2_cold(int showmessages, struct of_geom *ptrgeom, FTYPE *Avcon, FTYPE *Avcov, FTYPE *gammarel2return, FTYPE *deltareturn, FTYPE *numeratorreturn, FTYPE *divisorreturn, FTYPE *Erfreturn, FTYPE *urfconrel)
13940 {
13941  FTYPE gamma2,gammarel2,delta;
13942  FTYPE Erf;
13943  FTYPE alpha=ptrgeom->alphalapse;
13944  int jj;
13945 
13946  static FTYPE gctt, gn11, gn12, gn13, gn14, gn22, gn23, gn24, gn33, gn34, gn44, Rtt, Rtx, Rty, Rtz, Rdtt, Rdtx, Rdty, Rdtz;
13947  gn11=ptrgeom->gcon[GIND(0,0)];
13948  gn12=ptrgeom->gcon[GIND(0,1)];
13949  gn13=ptrgeom->gcon[GIND(0,2)];
13950  gn14=ptrgeom->gcon[GIND(0,3)];
13951  gn22=ptrgeom->gcon[GIND(1,1)];
13952  gn23=ptrgeom->gcon[GIND(1,2)];
13953  gn24=ptrgeom->gcon[GIND(1,3)];
13954  gn33=ptrgeom->gcon[GIND(2,2)];
13955  gn34=ptrgeom->gcon[GIND(2,3)];
13956  gn44=ptrgeom->gcon[GIND(3,3)];
13957 
13958  Rtt=Avcon[0];
13959  Rtx=Avcon[1];
13960  Rty=Avcon[2];
13961  Rtz=Avcon[3];
13962 
13963  Rdtt=Avcov[0];
13964  Rdtx=Avcov[1];
13965  Rdty=Avcov[2];
13966  Rdtz=Avcov[3];
13967 
13968 
13969  // choose gamma
13970  if(gammarel2return==NULL){
13971  FTYPE gammamax=GAMMAMAXRAD;
13972  FTYPE gammamaxfail=GAMMAMAXRADFAIL;
13973  gammarel2=gammamax*gammamax;
13974  }
13975  else gammarel2=*gammarel2return; // feed in desired gammarel2
13976 
13977  FTYPE utsq=gammarel2/(alpha*alpha);
13978 
13979 
13980  FTYPE Avcovorig[NDIM],Avconorig[NDIM];
13981  DLOOPA(jj) Avcovorig[jj]=Avcov[jj];
13982  DLOOPA(jj) Avconorig[jj]=Avcon[jj];
13983 
13984  // get new Avcov[0]=R^t_t
13985 
13986  // NOTEMARK: Note that Sqrt() is only ever negative when gammarel2<0, so never has to be concern.
13987  Avcov[0]=(0.25*(-4.*(gn12*Rdtx + gn13*Rdty + gn14*Rdtz)*utsq*(gn11 + utsq) +
13988  Sqrt((Power(gn12,2)*Power(Rdtx,2) + 2.*gn12*Rdtx*(gn13*Rdty + gn14*Rdtz) + Power(gn13*Rdty + gn14*Rdtz,2) -
13989  1.*gn11*(gn22*Power(Rdtx,2) + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) + 2.*gn24*Rdtx*Rdtz + 2.*gn34*Rdty*Rdtz +
13990  gn44*Power(Rdtz,2)))*utsq*(gn11 + utsq)*Power(gn11 + 4.*utsq,2))))/(gn11*utsq*(gn11 + utsq));
13991 
13992  Erf=(0.75*Sqrt((Power(gn12,2)*Power(Rdtx,2) + 2.*gn12*Rdtx*(gn13*Rdty + gn14*Rdtz) + Power(gn13*Rdty + gn14*Rdtz,2) -
13993  1.*gn11*(gn22*Power(Rdtx,2) + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) + 2.*gn24*Rdtx*Rdtz + 2.*gn34*Rdty*Rdtz +
13994  gn44*Power(Rdtz,2)))*utsq*(gn11 + utsq)*Power(gn11 + 4.*utsq,2)))/(utsq*(gn11 + utsq)*(gn11 + 4.*utsq));
13995 
13996  if(0&&showmessages && debugfail>=2) dualfprintf(fail_file,"NOR SOL: Avcov0new=%g Avcov0old=%g Erf=%g :: %g %g %g\n",Avcov[0],Avcovorig[0],Erf,Rtx,Rty,Rtz);
13997 
13998  //modify Avcon
13999  indices_12(Avcov,Avcon,ptrgeom);
14000  if(0&&showmessages && debugfail>=2) DLOOPA(jj) dualfprintf(fail_file,"jj=%d Avconorig=%g Avconnew=%g\n",jj,Avconorig[jj],Avcon[jj]);
14001 
14002 
14003  delta=0; // not yet
14004 
14005  if(0&&showmessages && debugfail>=2){
14006  // alt solution
14007 
14008  FTYPE Avcovalt = (-0.25*(4.*(gn12*Rdtx + gn13*Rdty + gn14*Rdtz)*utsq*(gn11 + utsq) +
14009  Sqrt((Power(gn12,2)*Power(Rdtx,2) + 2.*gn12*Rdtx*(gn13*Rdty + gn14*Rdtz) + Power(gn13*Rdty + gn14*Rdtz,2) -
14010  1.*gn11*(gn22*Power(Rdtx,2) + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) + 2.*gn24*Rdtx*Rdtz + 2.*gn34*Rdty*Rdtz +
14011  gn44*Power(Rdtz,2)))*utsq*(gn11 + utsq)*Power(gn11 + 4.*utsq,2))))/(gn11*utsq*(gn11 + utsq));
14012 
14013  FTYPE Erfalt=(-0.75*Sqrt((Power(gn12,2)*Power(Rdtx,2) + 2.*gn12*Rdtx*(gn13*Rdty + gn14*Rdtz) + Power(gn13*Rdty + gn14*Rdtz,2) -
14014  1.*gn11*(gn22*Power(Rdtx,2) + 2.*gn23*Rdtx*Rdty + gn33*Power(Rdty,2) + 2.*gn24*Rdtx*Rdtz + 2.*gn34*Rdty*Rdtz +
14015  gn44*Power(Rdtz,2)))*utsq*(gn11 + utsq)*Power(gn11 + 4.*utsq,2)))/(utsq*(gn11 + utsq)*(gn11 + 4.*utsq));
14016 
14017  if(showmessages && debugfail>=2) dualfprintf(fail_file,"ALT SOL: Avcovalt=%g Avcov0old=%g Erfalt=%g : %g %g %g\n",Avcovalt,Avcovorig[0],Erfalt,Rdtx,Rdty,Rdtz);
14018  }
14019 
14020 
14021  *gammarel2return=gammarel2;
14022  *deltareturn=delta;
14023 
14024  // get good relative velocity
14025  FTYPE gammarel=sqrt(gammarel2);
14026 
14027  // get relative 4-velocity
14028  if(Erf>0.0) SLOOPA(jj) urfconrel[jj] = alpha * (Avcon[jj] + 1./3.*Erf*ptrgeom->gcon[GIND(0,jj)]*(4.0*gammarel2-1.0) )/(4./3.*Erf*gammarel);
14029  else SLOOPA(jj) urfconrel[jj] = 0.0;
14030 
14031  if(0&&showmessages && debugfail>=2) dualfprintf(fail_file,"NORM ROOT 4-vel: %g %g %g : %g\n",urfconrel[1],urfconrel[2],urfconrel[3],ptrgeom->gdet);
14032 
14033 
14034  *Erfreturn=Erf; // pass back new Erf to pointer
14035 
14036 
14037  return(0);
14038 }
14039 
14040 
14041 
14042 
14043 
14044 
14045 
14046 
14047 
14048 
14049 
14050 
14051 
14052 
14053 
14054 
14055 
14056 
14057 
14058 
14059 
14060 
14061 
14062 
14063 
14064 
14065 
14066 
14067 
14068 
14069 
14070 
14071 
14072 
14073 
14074 
14076 int calc_tautot_chieff(FTYPE *pp, FTYPE chi, struct of_geom *ptrgeom, struct of_state *q, FTYPE *tautot, FTYPE *tautotmax)
14077 {
14078  //xx[0] holds time
14079  int NxNOT1[NDIM]={0,N1NOT1,N2NOT1,N3NOT1}; // want to ignore non-used dimensions
14080 
14081 
14082  // see averyboost.nb
14083  // dtau^jj = chi dxff^jj = chi dxlab^jj (1+\gamma - \gamma vjj^2)/(1+\gamma+vjj+\gamma vjj)
14084  // = chi dxlab^jj (\gamma + \gamma^2 - ux^2)/( (1+\gamma)*(\gamma+ux) )
14085  int jj;
14086  FTYPE dxorthoff[NDIM];
14087  FTYPE orthofactor[NDIM];
14088  FTYPE ujj,gamma;
14089  FTYPE ujjsq,gammasq;
14090  *tautotmax=0.0;
14091  FTYPE top,bottom;
14092  SLOOPA(jj){
14093 
14094  // orthofactor[jj] = 1.0/sqrt(fabs(ptrgeom->gcon[GIND(jj,jj)]));
14095 
14096  // NOTEMARK: only approximate near a rotating BH
14097  // ujj = q->ucon[jj]*orthofactor[jj];
14098  // NOTEMARK: only approximate near a rotating BH
14099  // gamma = q->ucon[TT]*orthofactor[jj]; // as if *ptrgeom->alphalapse
14100  // need gamma>|ujj| always, but if mixing ZAMO and lab, won't be true necessarily.
14101  // need ujj->0 to imply gamma->1 if other directions have u_{perp jj}=0, so should really use ujj as utilde^jj, but then not really correct ff->lab conversion if using gamma for relative to ZAMO
14102 
14103  if(q!=NULL){
14104  ujjsq = fabs(q->ucon[jj]*q->ucov[jj]); // because true -1 = u^t u_t + u^r u_r + u^h u_h + u^p u_p
14105  ujj = sqrt(ujjsq); //sign(q->ucon[jj])*
14106 
14107  gammasq = fabs(-q->ucon[TT]*q->ucov[TT]);
14108  gammasq = MAX(1.0,gammasq); // for near the rotating BH since not doing true orthonormal fluid frame.
14109  gamma = sqrt(gammasq);
14110 
14111 
14112  top=gamma + MAX(1.0,gammasq - ujjsq);
14113  top=MAX(top,2.0); // numerator can be no smaller than 2
14114 
14115  FTYPE vjj = ujj/gamma;
14116  vjj = MIN(1.0,vjj);
14117  bottom = (1.0+gamma)*gamma*(1.0+vjj); // ranges from 2 through infinity. vjj cannot be negative, as that would be a different Lorentz boost the wrong way.
14118  bottom = MAX(2.0,bottom);
14119 
14120  }
14121  else{
14122  // assume for cases when high accuracy not required, like shock detector
14123  top=1.0;
14124  bottom=top;
14125  }
14126 
14127  dxorthoff[jj] = (dx[jj]*orthofactor[jj]) * (top/bottom);
14128  tautot[jj]=chi * dxorthoff[jj];
14129 
14130  *tautotmax=MAX(*tautotmax,tautot[jj]*NxNOT1[jj]);
14131  }
14132 
14133  return 0;
14134 }
14135 
14136 int calcfull_tautot(FTYPE *pp, struct of_geom *ptrgeom, FTYPE *tautot, FTYPE *tautotmax)
14137 {
14138 
14139  struct of_state q;
14140  get_state(pp, ptrgeom, &q);
14141  calc_tautot(pp, ptrgeom, &q, tautot, tautotmax);
14142 
14143  return 0;
14144 
14145 }
14147 int calc_tautot(FTYPE *pp, struct of_geom *ptrgeom, struct of_state *q, FTYPE *tautot, FTYPE *tautotmax)
14148 {
14149  //xx[0] holds time
14150  FTYPE kappa,kappaes,chi;
14151  calc_kappa(pp,ptrgeom,q,&kappa);
14152  calc_kappaes(pp,ptrgeom,&kappaes);
14153  chi=kappa+kappaes;
14154 
14155  calc_tautot_chieff(pp,chi,ptrgeom,q,tautot,tautotmax);
14156 
14157  return 0;
14158 }
14159 
14160 
14161 
14162 
14163 
14164 
14167 {
14168  // if use local function function instead of below directly,
14169  // then assume user doesn't care about position for EOS.
14170  FTYPE u=u_rho0_T_simple(0, 0, 0, CENT, rho, T);
14171  return u;
14172 }
14173 
14175 {
14176  FTYPE T=compute_temp_simple(0, 0, 0, CENT, rho, u);
14177  return T;
14178 }
14179 
14182 {
14183  // return 4.*SIGMA_RAD*T*T*T*T;
14184  return (ARAD_CODE*T*T*T*T);
14185 }
14186 
14189 {
14190  return (ARAD_CODE*T*T*T/EBAR0); // i.e. average energy per photon is 2.7k_b T
14191 }
14192 
14195 {
14196  FTYPE T=calc_LTE_TfromE(E);
14197  return(calc_LTE_NfromT(T));
14198 }
14199 
14202 {
14203  // return sqrt(sqrt((E/4./SIGMA_RAD)));
14204  return (sqrt(sqrt((E/(SMALL+ARAD_CODE)))));
14205 }
14206 
14209 {
14210  FTYPE T=compute_temp_simple(0, 0, 0, CENT, rho, u);
14211  return (calc_LTE_EfromT(T));
14212 }
14213 
14214 
14215 
14217 int set_ncon_velocity(int whichvel, FTYPE gammamax, FTYPE *ncon, struct of_geom *ptrgeom, FTYPE *uconwhichvel)
14218 {
14219  int ii,jj;
14220  FTYPE ncondefault[NDIM]={0.0,-1.0, 0.0, 0.0}; //for radially flowing photons
14221  FTYPE *nconuse;
14222 
14223  // default is radial motion in zamo frame
14224  if(ncon==NULL) nconuse=ncondefault;
14225  else nconuse=ncon;
14226 
14227  // compute \gammarel using nconuse
14228  FTYPE gammatemp,qsq;
14229  gamma_calc_fromuconrel(nconuse,ptrgeom,&gammatemp,&qsq);
14230 
14231  // now rescale nconuse[i] so will give desired \gammamax
14232  FTYPE prtemp[NPR];
14233  SLOOPA(ii) prtemp[U1+ii-1] = nconuse[ii]*(gammamax/gammatemp);
14234 
14235  // now get u^\mu[lab]
14236  FTYPE uconlab[NDIM];
14238  ucon_calc_whichvel(WHICHVEL,prtemp,ptrgeom,uconlab,others);
14239 
14240  // now get other whichvel type
14241  FTYPE prtemp2[NPR];
14242  ucon2pr(whichvel,uconlab,ptrgeom,prtemp2);
14243 
14244  SLOOPA(jj) uconwhichvel[jj] = prtemp2[U1+jj-1];
14245 
14246  return(0);
14247 
14248 }
14249 
14250 
14251 
14252 //#include "phys.tools.rad.notused.c"
14253