HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
phys.tools.c
Go to the documentation of this file.
1 
6 #include "decs.h"
7 
8 
9 
10 
11 
12 // making variables static inside functions made things slower if anything
13 // would have thought consruction/destruction operations would be important
14 // why static makes slower?
15 //#define VARSTATIC static
16 #define VARSTATIC
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
33 int primtoflux(int returntype, FTYPE *pr, struct of_state *q, int dir,
34  struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs)
35 {
36  int primtoflux_ma(int needentropy,int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs, FTYPE *fluxdiag, FTYPE *fluxdiagabs);
37  int primtoflux_rad(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
38  int primtoflux_em(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
39  void UtoU_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
40  VARSTATIC FTYPE fluxinput[NPR],fluxinputma[NPR],fluxinputrad[NPR],fluxinputem[NPR];
41  VARSTATIC FTYPE fluxinputabs[NPR],fluxinputmaabs[NPR],fluxinputradabs[NPR],fluxinputemabs[NPR];
42  VARSTATIC FTYPE fluxdiag;
43  VARSTATIC FTYPE fluxdiagabs;
44  VARSTATIC int pl,pliter;
45 
46 
47 
48  // initialize fluxinputma and fluxinputem so individual functions only have to define non-zero terms
49  PLOOP(pliter,pl) fluxinput[pl]=fluxinputma[pl]=fluxinputrad[pl]=fluxinputem[pl]=0.0;
50  PLOOP(pliter,pl) fluxinputabs[pl]=fluxinputmaabs[pl]=fluxinputradabs[pl]=fluxinputemabs[pl]=0.0;
51  fluxdiag=0.0;
52 
53 
54  // define MA terms
55  primtoflux_ma(1,&returntype, pr, q, dir, geom, fluxinputma, fluxinputmaabs, &fluxdiag, &fluxdiagabs);
56  fluxinputma[UU+dir]+=fluxdiag; // add back to normal term
57  fluxinputmaabs[UU+dir]+=fluxdiagabs; // add back to normal term
58  // add up MA
59  PLOOP(pliter,pl){
60  fluxinput[pl] += fluxinputma[pl];
61  fluxinputabs[pl] += fluxinputmaabs[pl];
62  }
63 
65  // define RAD terms
66  primtoflux_rad(&returntype, pr, q, dir, geom, fluxinputrad, fluxinputradabs);
67  // add up RAD
68  PLOOP(pliter,pl){
69  fluxinput[pl] += fluxinputrad[pl];
70  fluxinputabs[pl] += fluxinputradabs[pl];
71  }
72  }
73 
74  // define EM terms
75  primtoflux_em(&returntype, pr, q, dir, geom, fluxinputem, fluxinputemabs);
76  // add up EM
77  PLOOP(pliter,pl){
78  fluxinput[pl] += fluxinputem[pl];
79  fluxinputabs[pl] += fluxinputemabs[pl];
80  }
81 
82 
83  // DEBUG:
84  // if((fabs(pr[U1])>1.0 || fabs(fluxinput[U1])>1.0) && (geom->i==10 || geom->i==9 || geom->i==11)&&(geom->k==0 || geom->k==-1 || geom->k==1)) PALLLOOP(pl) dualfprintf(fail_file,"ALLBEFORE: ijk=%d %d %d : pl=%d pr=%g flux=%21.15g\n",geom->i,geom->j,geom->k,pl,pr[pl],fluxinput[pl]);
85 
86 
87  // convert from UNOTHING->returntype
88  // notice that geometry comes after subtractions/additions of EOMs
89  UtoU_fromunothing(returntype,geom,fluxinput,flux);
90  if(fluxabs!=NULL) UtoU_fromunothing(returntype,geom,fluxinputabs,fluxabs);
91 
92 
93 
94  // DEBUG:
95  // PALLLOOP(pl) dualfprintf(fail_file,"ALLAFTER: pl=%d flux=%21.15g\n",pl,flux[pl]);
96 
97 
98  return(0);
99 
100 }
101 
102 
103 
104 
105 int primtoflux_nonradonly(int needentropy, FTYPE *pr, struct of_state *q, int dir,
106  struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs)
107 {
108  int primtoflux_ma(int needentropy,int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs, FTYPE *fluxdiag, FTYPE *fluxdiagabs);
109  int primtoflux_em(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
110  VARSTATIC FTYPE fluxma[NPR],fluxem[NPR];
111  VARSTATIC FTYPE fluxmaabs[NPR],fluxemabs[NPR];
112  // VARSTATIC FTYPE fluxdiag;
113  // VARSTATIC FTYPE fluxdiagabs;
114  VARSTATIC int pl,pliter;
115  int returntype=UNOTHING;
116 
117 
118  // initialize fluxma and fluxem so individual functions only have to define non-zero terms
119  PLOOP(pliter,pl) flux[pl]=fluxma[pl]=fluxem[pl]=0.0;
120  PLOOP(pliter,pl) fluxmaabs[pl]=fluxemabs[pl]=0.0;
121  if(fluxabs!=NULL) PLOOP(pliter,pl) fluxabs[pl]=0.0;
122  // fluxdiag=0.0;
123  // fluxdiagabs=0.0;
124 
125 
126  // define MA terms
127  primtoflux_ma(needentropy,&returntype, pr, q, dir, geom, fluxma, fluxmaabs, NULL, NULL);
128  // fluxma[UU+dir]+=fluxdiag; // add back to normal term
129  // fluxmaabs[UU+dir]+=fluxdiagabs; // add back to normal term
130  // add up MA
131  PLOOP(pliter,pl){
132  flux[pl] += fluxma[pl];
133  if(fluxabs!=NULL) fluxabs[pl] += fluxmaabs[pl];
134  }
135 
136 
137  // define EM terms
138  primtoflux_em(&returntype, pr, q, dir, geom, fluxem, fluxemabs);
139  // add up EM
140  PLOOP(pliter,pl){
141  flux[pl] += fluxem[pl];
142  if(fluxabs!=NULL) fluxabs[pl] += fluxemabs[pl];
143  }
144 
145 
146  // returns UNOTHING form
147 
148  return(0);
149 }
150 
151 int primtoflux_radonly(FTYPE *pr, struct of_state *q, int dir,
152  struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs)
153 {
154  int primtoflux_rad(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
155  VARSTATIC FTYPE fluxrad[NPR];
156  VARSTATIC FTYPE fluxradabs[NPR];
157  // VARSTATIC FTYPE fluxdiag;
158  VARSTATIC int pl,pliter;
159  int returntype=UNOTHING;
160 
161 
162 
163  PLOOP(pliter,pl) flux[pl]=fluxrad[pl]=0.0;
164  if(fluxabs!=NULL) PLOOP(pliter,pl) fluxabs[pl]=0.0;
165 
166 
167  if(EOMRADTYPE!=EOMRADNONE){
168  // define RAD terms
169  primtoflux_rad(&returntype, pr, q, dir, geom, fluxrad, fluxradabs);
170  // add up RAD
171  PLOOP(pliter,pl){
172  flux[pl] += fluxrad[pl];
173  if(fluxabs!=NULL) fluxabs[pl] += fluxradabs[pl];
174  }
175  }
176 
177  // returns UNOTHING form
178 
179  return(0);
180 }
181 
182 
183 
184 
185 /* calculate fluxes in direction dir and conserved variable U; these
186  are always needed together, so there is no point in calculated the
187  stress tensor twice */
188 
193 int primtoflux_splitmaem(int returntype, FTYPE *pr, struct of_state *q, int fluxdir, int fundir, struct of_geom *geom, FTYPE *fluxma, FTYPE *fluxem)
194 {
195  int primtoflux_ma(int needentropy,int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs, FTYPE *fluxdiag, FTYPE *fluxdiagabs);
196  int primtoflux_rad(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
197  int primtoflux_em(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs);
198  void UtoU_ma_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
199  void UtoU_rad_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
200  void UtoU_em_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
201  VARSTATIC FTYPE fluxinput[NPR],fluxinputma[NPR],fluxinputrad[NPR],fluxinputem[NPR];
202  VARSTATIC FTYPE fluxdiag;
203  VARSTATIC int pl,pliter;
204  FTYPE fluxrad[NPR];
205 
206  // initialize fluxinputma and fluxinputrad+fluxinputem so individual functions only have to define non-zero terms
207  PLOOP(pliter,pl) fluxinputma[pl]=fluxinputrad[pl]=fluxinputem[pl]=0.0;
208 
209  // define MA terms
210  primtoflux_ma(1,&returntype, pr, q, fundir, geom, fluxinputma, NULL, &fluxdiag, NULL);
211 
212  // SUPERGODMARK CHANGINGMARK
213  // Note that pressure part of flux has 0 conserved quantity associated with it from the point of view of this output and correct HLL/LAXF calculation
214 #if(1)
215  if(fundir!=TT) fluxinputma[FLUXSPLITPMA(fluxdir)]=fluxdiag;
216  else fluxinputma[UU]+=fluxdiag;
217 
218  // if(fundir!=TT) fluxinputma[FLUXSPLITPMA(fundir)]=fluxdiag; // only need to return single diagonal value and store it inside field part for now
219  // else fluxinputma[UU]+=fluxdiag; // then really part of conserved quantity and then don't separate it
220 
221 #elif(0)
222 
223  // not as robust to put conserved quantity here such that dissipative term is not together with momentum-flux_dir_dir term
224  fluxinputma[FLUXSPLITPMA(fluxdir)]=fluxdiag; // only need to return single diagonal value and store it inside field part for now
225 #else
226  // not as robust to put conserved quantity here such that dissipative term is not together with momentum-flux_dir_dir term
227  if(fundir!=TT) fluxinputma[FLUXSPLITPMA(fluxdir)]=fluxdiag;
228  else{
229  fluxinputma[UU]+=0.5*fluxdiag;
230  fluxinputma[FLUXSPLITPMA(fluxdir)]=0.5*fluxdiag;
231  }
232 #endif
233  // convert from UNOTHING->returntype
234  // notice that geometry comes after subtractions/additions of EOMs
235  // UtoU_ma(UNOTHING,returntype,geom,fluxinputma,fluxma); // properly converts separate diagonal flux in FLUXSPLITPMA(fluxdir)
236  UtoU_ma_fromunothing(returntype,geom,fluxinputma,fluxma);
237 
238 
239  if(EOMRADTYPE!=EOMRADNONE){
240 
241  // define RAD terms (as separate fluid from MHD fluid)
242  primtoflux_rad(&returntype, pr, q, fundir, geom, fluxinputrad, NULL);
243 
244  // UtoU_rad(UNOTHING,returntype,geom,fluxinputrad,fluxrad);
245  UtoU_rad_fromunothing(returntype,geom,fluxinputrad,fluxrad);
246 
247  PLOOP(pliter,pl) fluxma[pl]+=fluxrad[pl]; // KORAL: Just add RAD to MA for this split approach
248  }
249 
250  // define EM terms
251  primtoflux_em(&returntype, pr, q, fundir, geom, fluxinputem, NULL);
252  // UtoU_em(UNOTHING,returntype,geom,fluxinputem,fluxem);
253  UtoU_em_fromunothing(returntype,geom,fluxinputem,fluxem);
254 
255 
256 
257  return(0);
258 
259 }
260 
261 
262 
264 int primtoflux_ma(int needentropy,int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs, FTYPE *fluxdiag, FTYPE *fluxdiagabs)
265 {
266  // sizes: NPR,struct of_state, int, struct of_geom, NPR
267  int ynuflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum);
268  int ylflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum);
269  int yflflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum);
270  int massflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *massflux, FTYPE *massfluxabs);
271  int entropyflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *entropyflux, FTYPE *entropyfluxabs);
272  VARSTATIC FTYPE fluxdiagpress[NPR]; // temp var
273  VARSTATIC FTYPE fluxdiagpressabs[NPR]; // temp var
274  VARSTATIC int pl,pliter;
275 
276  // USE of SPLITNPR here is simplified for speed
277  // assume if quantity is bracketed that including it
278 
279 
280 #if(SPLITNPR)
281  if(nprlist[nprstart]<=RHO && nprlist[nprend]>=RHO)
282 #endif
283  massflux_calc(pr, dir, q, &flux[RHO], &fluxabs[RHO]); // fills RHO only
284 
285 
286  // GODMARK WTF! Problems with code (compiling?) with this
287  // if(mhd_calc(pr,dir,geom,q,mhd,mhdabs)>=1)
288  // FAILSTATEMENT("phys.c:primtoflux()","mhd_calc() dir=1or2",1);
289 
290  // MHD stress-energy tensor w/ first index up, second index down.
291 #if(SPLITNPR)
292  if(nprlist[nprstart]<=UU && nprlist[nprend]>=U3)
293 #endif
294  {
295  mhd_calc_ma(pr, dir, geom, q, &flux[UU], &fluxabs[UU], &fluxdiagpress[UU], &fluxdiagpressabs[UU]); // fills flux[UU->U3] and fluxdiagonal[UU->U3]
296  if(fluxdiag!=NULL) *fluxdiag = fluxdiagpress[UU+dir];
297  if(fluxdiagabs!=NULL) *fluxdiagabs = fluxdiagpressabs[UU+dir];
298  }
299 
300  // dualfprintf(fail_file,"fluxdiagabs=%g\n",*fluxdiagabs);
301 
302 
303 
304 
305 #if(YFL1>=0)
306 #if(SPLITNPR)
307  if(nprlist[nprstart]<=YFL1 && nprlist[nprend]>=YFL1)
308 #endif
309  yflflux_calc(geom,pr, dir, q, &flux[YFL1], &fluxabs[YFL1],YFL1); // fills YFL1 only
310 #endif
311 
312 #if(YFL2>=0)
313 #if(SPLITNPR)
314  if(nprlist[nprstart]<=YFL2 && nprlist[nprend]>=YFL2)
315 #endif
316  yflflux_calc(geom,pr, dir, q, &flux[YFL2], &fluxabs[YFL2],YFL2); // fills YFL2 only
317 #endif
318 
319 #if(YFL3>=0)
320 #if(SPLITNPR)
321  if(nprlist[nprstart]<=YFL3 && nprlist[nprend]>=YFL3)
322 #endif
323  yflflux_calc(geom,pr, dir, q, &flux[YFL3], &fluxabs[YFL3],YFL3); // fills YFL3 only
324 #endif
325 
326 
327 
328 
329 
330 #if(DOYL!=DONOYL)
331 #if(SPLITNPR)
332  if(nprlist[nprstart]<=YL && nprlist[nprend]>=YL)
333 #endif
334  ylflux_calc(geom,pr, dir, q, &flux[YL], &fluxabs[YL],YL); // fills YL only
335 #endif
336 #if(DOYNU!=DONOYNU)
337 #if(SPLITNPR)
338  if(nprlist[nprstart]<=YNU && nprlist[nprend]>=YNU)
339 #endif
340  ynuflux_calc(geom, pr, dir, q, &flux[YNU], &fluxabs[YNU],YNU); // fills YNU only
341 #endif
342 
343 
344 #if(DOENTROPY!=DONOENTROPY)
345  if(needentropy){
346 #if(SPLITNPR)
347  if(nprlist[nprstart]<=ENTROPY && nprlist[nprend]>=ENTROPY)
348 #endif
349  entropyflux_calc(pr, dir, q, &flux[ENTROPY], &fluxabs[ENTROPY]); // fills ENTROPY only
350 
351  // below is special for utoprim() 5D version for full entropy evolution and inversion
352  if(*returntype==UENTROPY){
353  flux[UU]=flux[ENTROPY]; // overwrite for utoprim()
354  fluxabs[UU]=fluxabs[ENTROPY]; // overwrite for utoprim()
355  if(fluxdiag!=NULL) *fluxdiag = 0.0; // overwrite for utoprim()
356  if(fluxdiagabs!=NULL) *fluxdiagabs = 0.0; // overwrite for utoprim()
357  *returntype=UNOTHING; // reset returntype for UtoU
358  }
359  }
360 
361 #endif
362 
363 
364  // DEBUG:
365  // PALLLOOP(pl) dualfprintf(fail_file,"ALL: pl=%d flux=%21.15g\n",pl,flux[pl]);
366 
367 
368  return (0);
369 }
370 
371 
372 
374 int primtoflux_rad(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs)
375 {
376  int yflflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum);
377 
378  // Radiation stress-energy tensor w/ first index up, second index down.
379 #if(SPLITNPR)
380 #error "primtoflux_rad not setup for SPLITNPR"
381 #endif
382 
383  if(EOMRADTYPE!=EOMRADNONE){
384  mhd_calc_rad(pr, dir, geom, q, &flux[URAD0], &fluxabs[URAD0]); // fills URAD0->URAD3
385  }
386  // else don't fill flux[RAD0->RAD3] since assume entries don't exist
387 
388 #if(YFL4>=0)
389 #if(SPLITNPR)
390  if(nprlist[nprstart]<=YFL4 && nprlist[nprend]>=YFL4)
391 #endif
392  yflflux_calc(geom,pr, dir, q, &flux[YFL4], &fluxabs[YFL4],YFL4); // fills YFL4 only
393 #endif
394 
395 #if(YFL5>=0)
396 #if(SPLITNPR)
397  if(nprlist[nprstart]<=YFL5 && nprlist[nprend]>=YFL5)
398 #endif
399  yflflux_calc(geom,pr, dir, q, &flux[YFL5], &fluxabs[YFL5],YFL5); // fills YFL5 only
400 #endif
401 
402 
403 
404  return (0);
405 }
406 
407 
409 int primtoflux_em(int *returntype, FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *flux, FTYPE *fluxabs)
410 {
411  // sizes: NPR,struct of_state, int, struct of_geom, NPR
412  // FTYPE dualf[NDIM];
413  // int massflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *massflux, FTYPE *massfluxabs);
414  // int advectedscalarflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum);
415 
416 
417  // USE of SPLITNPR here is simplified for speed
418  // assume if quantity is bracketed that including it
419 
420 
421  // GODMARK WTF! Problems with code (compiling?) with this
422  // if(mhd_calc(pr,dir,geom,q,mhd,mhdabs)>=1)
423  // FAILSTATEMENT("phys.c:primtoflux()","mhd_calc() dir=1or2",1);
424 
425  // MHD stress-energy tensor w/ first index up, second index down.
426 #if(SPLITNPR)
427  if(nprlist[nprstart]<=UU && nprlist[nprend]>=U3)
428 #endif
429  mhd_calc_em(pr, dir, geom, q, &flux[UU], &fluxabs[UU]); // fills UU->U3
430 
431 
432 
433 #if(SPLITNPR)
434  if(nprlist[nprstart]<=B1 && nprlist[nprend]>=B3)
435 #endif
436  dualfaradayspatial_calc(pr,dir,q,&flux[B1],&fluxabs[B1]); // fills B1->B3
437 
438 
439 #if(DEBUGNSBH)
440  // DEBUG:
441  if(geom->i==26 && geom->j==40 && dir==1){
442  dualfprintf(fail_file,"INprimetoflux_em: %21.15g %21.15g %21.15g\n",flux[B1],flux[B2],flux[B3]);
443  }
444 #endif
445 
446 
447  return (0);
448 }
449 
450 
451 int massflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *massflux, FTYPE *massfluxabs)
452 {
453  // particle number flux
454  *massflux = pr[RHO] * q->ucon[dir];
455  *massfluxabs=fabs(*massflux);
456 
457  // DEBUG:
458  // dualfprintf(fail_file,"massflux: %d %21.15g %21.15g\n",dir,pr[RHO],q->ucon[dir]);
459 
460  return(0);
461 }
462 
463 
465 int yflflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum)
466 {
467  FTYPE prforadvect;
468 
469  FTYPE udir=0.0;
470  if(pnum==YFL1 || pnum==YFL2 || pnum==YFL3) udir=q->ucon[dir];
471  if(pnum==YFL4 || pnum==YFL5) udir=q->uradcon[dir];
472 
473  prforadvect = pr[pnum];
474 
475 #if(DOYFL==1)
476  // equation is d_t(\rho_0 u^t y) = d_i (\rho_0 u^i y)
477  // get flux associated with Y_L
478  *advectedscalarflux = prforadvect * pr[RHO]*udir; // y form
479 #elif(DOYFL==2)
480  // equation is d_t(rhofl u^t) = d_i (rhofl u^i)
481  // equation is d_t(T^t_t/u^t u^t) = d_i (T^t_t/u^t u^i)
482  // equation is d_t(T^t_\phi/u^t u^t) = d_i (T^t_\phi/u^t u^i)
483  // etc.
484  *advectedscalarflux = prforadvect * udir; // rho form
485 #endif
486 
487 
488  *advectedscalarfluxabs = fabs(*advectedscalarflux);
489 
490  return(0);
491 }
492 
494 int ylflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum)
495 {
496  int massflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *massflux, FTYPE *massfluxabs);
497  VARSTATIC FTYPE massflux;
498  VARSTATIC FTYPE massfluxabs;
499  FTYPE prforadvect;
500 
501  // get mass flux
502  massflux_calc(pr, dir, q, &massflux, &massfluxabs);
503 
504 #if(WHICHEOS==KAZFULL)
505  yl2advect_kazfull(GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),pr[YL],pr[YNU],&prforadvect);
506 #else
507  prforadvect = pr[pnum];
508 #endif
509 
510  // get flux associated with Y_L
511  *advectedscalarflux = prforadvect * massflux;
512 
513  *advectedscalarfluxabs = fabs(*advectedscalarflux);
514 
515  return(0);
516 }
517 
518 
520 int ynuflux_calc(struct of_geom *ptrgeom, FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum)
521 {
522  int massflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *massflux, FTYPE *massfluxabs);
523  VARSTATIC FTYPE massflux, massfluxabs;
524  FTYPE prforadvect;
525 
526 
527  // get mass flux
528  massflux_calc(pr, dir, q, &massflux, &massfluxabs);
529 
530 #if(WHICHEOS==KAZFULL)
531  ynu2advect_kazfull(GLOBALMAC(EOSextraglobal,ptrgeom->i,ptrgeom->j,ptrgeom->k),pr[YL],pr[YNU],&prforadvect);
532 #else
533  prforadvect = pr[pnum];
534 #endif
535 
536  // get flux associated with Y_\nu
537  *advectedscalarflux = prforadvect * massflux;
538 
539  *advectedscalarfluxabs = fabs(*advectedscalarflux);
540 
541  return(0);
542 }
543 
544 
545 
547 int advectedscalarflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *advectedscalarflux, FTYPE *advectedscalarfluxabs, int pnum)
548 {
549  int massflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *massflux, FTYPE *massfluxabs);
550  VARSTATIC FTYPE massflux;
551  VARSTATIC FTYPE massfluxabs;
552 
553  // yflx/yl/ynu/etc. per unit rest-mass flux
554 
555  // entropy=entropy per unit volume, where conserved quantity is specific entropy:
556  // d/d\tau(entropy/rho)=0
557  // -> \nabla_\mu(entropy u^\mu)=0
558 
559  massflux_calc(pr, dir, q, &massflux, &massfluxabs);
560  *advectedscalarflux = pr[pnum] * massflux;
561  *advectedscalarfluxabs = fabs(*advectedscalarflux);
562 
563  return(0);
564 }
565 
566 
567 
569 int entropyflux_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *entropyflux, FTYPE *entropyfluxabs)
570 {
571 
572  // get entropy
573  // entropy_calc(ptrgeom,pr,&entropy); // now done in get_state_thermodynamics()
574  // entropy per unit rest-mass flux
575  // entropy=entropy per unit volume, where conserved quantity is specific entropy:
576  // d/d\tau(entropy/rho)=0
577  // -> \nabla_\mu(entropy u^\mu)=0
578 
579  // SUPERKORALTODO: With an non-zero \kappa, thermal flux exists between fluid and radiation. Below does not account for this. See http://adsabs.harvard.edu/abs/2012MNRAS.426.1613R APPENDIX A. They don't give general expression, but should be a G_\mu term that enters.
580  //
581  // d/d\tau(entropy/rho)=d/\tau SOURCE
582  // -> \nabla_\mu(entropy u^\mu)= ...
583 
584 
585  // DEBUG:
586  //dualfprintf(fail_file,"entropy=%21.15g dir=%d ucondir=%21.15g\n",entropy,dir,q->ucon[dir]);
587 
588  *entropyflux = (q->entropy) * (q->ucon[dir]);
589 
590  *entropyfluxabs = fabs(*entropyflux);
591 
592  return(0);
593 }
594 
595 
596 
597 
599 int dualfaradayspatial_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *dualf, FTYPE *dualfabs)
600 {
601  VARSTATIC FTYPE dualffull[NDIM];
602 
603 
604  dualfullfaraday_calc(pr,dir,q,dualffull);
605  dualf[0]=dualffull[1];
606  dualf[1]=dualffull[2];
607  dualf[2]=dualffull[3];
608 
609  dualfabs[0]=fabs(dualf[0]);
610  dualfabs[1]=fabs(dualf[1]);
611  dualfabs[2]=fabs(dualf[2]);
612 
613 
614  return(0);
615 
616 }
617 
618 
619 
633 int dualfullfaraday_calc(FTYPE *pr, int dir, struct of_state *q, FTYPE *dualffull)
634 {
635 
636 #if(MAXWELL==GENMAXWELL)
637  // dual of Maxwell tensor
638  dualffull[0] = q->bcon[0] * q->ucon[dir] - q->bcon[dir] * q->ucon[0];
639  dualffull[1] = q->bcon[1] * q->ucon[dir] - q->bcon[dir] * q->ucon[1];
640  dualffull[2] = q->bcon[2] * q->ucon[dir] - q->bcon[dir] * q->ucon[2];
641  dualffull[3] = q->bcon[3] * q->ucon[dir] - q->bcon[dir] * q->ucon[3];
642 #elif(MAXWELL==PRIMMAXWELL)
643  if(dir>0){
644  // dual of Maxwell tensor
645  // dir refers to the direction of the derivative of the dualffull
646  // B1,B2,B3 refers to LHS of equation dB^i/dt
647  // due to antisymmetry, dir==i is 0
648  dualffull[0] = - pr[B1+dir-1] ; // dualffull[i]=\dF^{i dir} where \dF^{0 dir} =-B^{dir}
649  dualffull[1] = (pr[B1] * q->ucon[dir] - pr[B1+dir-1] * q->ucon[1])/q->ucon[0];
650  dualffull[2] = (pr[B2] * q->ucon[dir] - pr[B1+dir-1] * q->ucon[2])/q->ucon[0];
651  dualffull[3] = (pr[B3] * q->ucon[dir] - pr[B1+dir-1] * q->ucon[3])/q->ucon[0];
652  }
653  else{
654  dualffull[0] = 0;
655  dualffull[1] = pr[B1];
656  dualffull[2] = pr[B2];
657  dualffull[3] = pr[B3];
658  }
659 #endif
660 
661  return(0);
662 
663 }
664 
665 
668 int Mcon_calc(FTYPE *pr, struct of_state *q, FTYPE (*Mcon)[NDIM])
669 {
670  VARSTATIC int j,k;
671  VARSTATIC FTYPE vcon[NDIM];
672 
673 
674 #if(MAXWELL==GENMAXWELL)
675 
676  DLOOP(j,k) Mcon[j][k] = q->bcon[j] * q->ucon[k] - q->bcon[k] * q->ucon[j];
677 
678 #elif(MAXWELL==PRIMMAXWELL)
679 
680  // diagonal is 0
681  DLOOPA(j) Mcon[j][j]=0.0;
682 
683  // space-time terms
684  SLOOPA(k) {
685  // \dF^{it} = B^i = pr[B1+i-1]
686  Mcon[k][0] = pr[B1+k-1] ;
687  Mcon[0][k] = - Mcon[k][0] ;
688  }
689 
690  // get v^i
691  SLOOPA(k) vcon[k]= q->ucon[k]/q->ucon[TT];
692 
693  // space-space terms
694  // SLOOP(j,k) Mcon[j][k] = (pr[B1+j-1] * vcon[k] - pr[B1+k-1] * vcon[j]);
695  // optimize
696  Mcon[1][2] = (pr[B1] * vcon[2] - pr[B2] * vcon[1]);
697  Mcon[1][3] = (pr[B1] * vcon[3] - pr[B3] * vcon[1]);
698  Mcon[2][3] = (pr[B2] * vcon[3] - pr[B3] * vcon[2]);
699  Mcon[2][1] = -Mcon[1][2];
700  Mcon[3][1] = -Mcon[1][3];
701  Mcon[3][2] = -Mcon[2][3];
702  Mcon[1][1] = Mcon[2][2] = Mcon[3][3] = 0.0;
703 
704 #endif
705 
706 
707  return(0);
708 
709 }
710 
711 
712 
714 int primtofullflux(int returntype, FTYPE *pr, struct of_state *q,
715  struct of_geom *ptrgeom, FTYPE (*flux)[NPR], FTYPE (*fluxabs)[NPR])
716 {
717  VARSTATIC int j;
718 
719  // j=0,1,2,3 corresponding to U^j_\nu , where \nu corresponds to all EOMs and j to space-time for each
720  // 1 stands for obey nprlist
721  DLOOPA(j) primtoflux(returntype,pr,q,j,ptrgeom,flux[j],fluxabs[j]);
722 
723  return(0);
724 }
725 
726 
728 int primtoU(int returntype, FTYPE *pr, struct of_state *q, struct of_geom *geom,
729  FTYPE *U,
730  FTYPE *Uabs)
731 {
732  MYFUN(primtoflux(returntype,pr, q, 0, geom, U, Uabs) ,"phys.c:primtoU()", "primtoflux_calc() dir=0", 1);
733 
734  return (0);
735 }
736 
737 
738 
739 
740 void UtoU_gen(int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
741 {
742  void UtoU_gen_gengdet(int removemass, int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
743  void UtoU_gen_allgdet(int removemass, int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
744  VARSTATIC int removemass;
745 
746 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
747  removemass = (whichmaem==ISMAONLY || whichmaem==ISMAANDEM);
748 #else
749  // otherwise removemass = 0 effectively
750  removemass = 0;
751 #endif
752 
753 #if(WHICHEOM!=WITHGDET)
754  UtoU_gen_gengdet(removemass, whichmaem, inputtype, returntype,ptrgeom,Uin, Uout);
755 #else
756  UtoU_gen_allgdet(removemass, whichmaem, inputtype, returntype,ptrgeom,Uin, Uout);
757 #endif
758 
759 }
760 
761 
762 void UtoU_gen_fromunothing(int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
763 {
764  void UtoU_gen_gengdet_fromunothing(int removemass, int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
765  void UtoU_gen_allgdet_fromunothing(int removemass, int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
766  VARSTATIC int removemass;
767 
768 
769 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
770  removemass = (whichmaem==ISMAONLY || whichmaem==ISMAANDEM);
771 #else
772  // otherwise removemass = 0 effectively
773  removemass = 0;
774 #endif
775 
776 
777 #if(WHICHEOM!=WITHGDET)
778  UtoU_gen_gengdet_fromunothing(removemass, whichmaem, returntype,ptrgeom,Uin, Uout);
779 #else
780  UtoU_gen_allgdet_fromunothing(removemass, whichmaem, returntype,ptrgeom,Uin, Uout);
781 #endif
782 
783 }
784 
785 
794 void UtoU_gen_gengdet(int removemass, int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
795 {
796  void UtoU_gen_gengdet_fromunothing(int removemass, int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Ugeomfree, FTYPE *Uout);
797  VARSTATIC FTYPE Ugeomfree[NPR];
798  VARSTATIC int pl,pliter;
799 
800 
801 
802 
803  if(inputtype==returntype){
804  // then just copy
805  PLOOP(pliter,pl) Uout[pl]=Uin[pl];
806  }
807  else{
808 
810  //
811  // input
812  //
813 
814  // set basic transformation
815  PLOOP(pliter,pl) Ugeomfree[pl]=Uin[pl];
816 
817  // now fine-tune transformation
818  switch(inputtype){
819 
820  case UEVOLVE:
821 
822  // get igdet
823  set_igdet(ptrgeom);
824 
825  PLOOP(pliter,pl) Ugeomfree[pl] *= ptrgeom->IEOMFUNCNOSINGMAC(pl);
826 
827  // dualfprintf(fail_file,"diff: %21.15g %21.15g\n",ptrgeom->EOMFUNCMAC(UU),MACP0A1(gdetvol,ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p));
828 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
829  if(removemass){
830  // go back to standard stress-energy tensor form
831  Ugeomfree[UU] += - Ugeomfree[RHO] ; // - means adding back rest-mass
832  }
833 #endif
834  break;
835  case UDIAG:
836  // get igdet
837  set_igdet(ptrgeom);
838 
839  PLOOP(pliter,pl) Ugeomfree[pl] *= ptrgeom->igdetnosing;
840  break;
841  case UNOTHING:
842  break;
843  default:
844  dualfprintf(fail_file,"UtoU: No such inputtype=%d\n",inputtype);
845  myexit(246364);
846  break;
847  }
848 
849 
850  // at this point, Ugeomfree is geometry-free standard form of conserved quantities
851  // output
852  UtoU_gen_gengdet_fromunothing(removemass, whichmaem, returntype,ptrgeom,Ugeomfree, Uout);
853 
854  }
855 
856 }
857 
858 
859 
860 
861 
862 void UtoU_gen_gengdet_fromunothing(int removemass, int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Ugeomfree, FTYPE *Uout)
863 {
864  VARSTATIC int pl,pliter;
865 
866 
868  //
869  // output
870  //
871  switch(returntype){
872  case UEVOLVE:
873 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
874  if(removemass){ // diagnostics want normal stress-energy tensor
875  // "subtract" rest-mass
876  // should be done on geometry-free version
877  Ugeomfree[UU] += Ugeomfree[RHO];
878  }
879 #endif
880  PLOOP(pliter,pl) Uout[pl]=Ugeomfree[pl]*ptrgeom->EOMFUNCMAC(pl);
881  break;
882  case UDIAG:
883  PLOOP(pliter,pl) Uout[pl]=Ugeomfree[pl]*ptrgeom->gdet;
884  break;
885  case UNOTHING:
886  PLOOP(pliter,pl) Uout[pl]=Ugeomfree[pl];
887  break;
888  default:
889  dualfprintf(fail_file,"UtoU: No such returntype=%d\n",returntype);
890  myexit(724365);
891  break;
892  }
893 
894 }
895 
896 
897 
898 
900 void UtoU_gen_allgdet(int removemass, int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
901 {
902  VARSTATIC FTYPE Ugeomfree[NPR];
903  VARSTATIC int pl,pliter;
904  void UtoU_gen_allgdet_fromunothing(int removemass, int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Ugeomfree, FTYPE *Uout);
905 
906 
907 
908 #if(WHICHEOM!=WITHGDET)
909  dualfprintf(fail_file,"Using UtoU_gen_allgdet() but WHICHEOM!=WITHGDET\n");
910  myexit(342968346);
911 #endif
912 
913 
914 
915 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
916  removemass = (whichmaem==ISMAONLY || whichmaem==ISMAANDEM);
917 #endif// otherwise removemass = 0 effectively
918 
919 
921  //
922  // input
923  //
924 
925  // now fine-tune transformation
926  switch(inputtype){
927 
928  case UEVOLVE:
929  case UDIAG:
930 
931  // get igdet
932  set_igdetsimple(ptrgeom);
933 
934  PLOOP(pliter,pl) Ugeomfree[pl] = Uin[pl]*ptrgeom->igdetnosing;
935 
936 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
937  if(removemass){
938  // go back to standard stress-energy tensor form
939  Ugeomfree[UU] += - Ugeomfree[RHO] ; // - means adding back rest-mass
940  }
941 #endif
942  break;
943  case UNOTHING:
944  PLOOP(pliter,pl) Ugeomfree[pl] = Uin[pl];
945  break;
946  default:
947  dualfprintf(fail_file,"UtoU: No such inputtype=%d\n",inputtype);
948  myexit(6746364);
949  break;
950  }
951 
952 
953  // at this point, Ugeomfree is geometry-free standard form of conserved quantities
954  // output
955  UtoU_gen_allgdet_fromunothing(removemass, whichmaem, returntype,ptrgeom,Ugeomfree, Uout);
956 
957 
958 }
959 
960 
961 
962 void UtoU_gen_allgdet_fromunothing(int removemass, int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Ugeomfree, FTYPE *Uout)
963 {
964  VARSTATIC int pl,pliter;
965 
967  //
968  // output
969  //
970  switch(returntype){
971  case UEVOLVE:
972  case UDIAG:
973 #if((REMOVERESTMASSFROMUU==1)&&(DOEVOLVERHO))
974  if(removemass){ // diagnostics want normal stress-energy tensor
975  // "subtract" rest-mass
976  // should be done on geometry-free version
977  Ugeomfree[UU] += Ugeomfree[RHO];
978  }
979 #endif
980  PLOOP(pliter,pl) Uout[pl]=Ugeomfree[pl]*ptrgeom->gdet;
981  break;
982  case UNOTHING:
983  PLOOP(pliter,pl) Uout[pl]=Ugeomfree[pl];
984  break;
985  default:
986  dualfprintf(fail_file,"UtoU: No such returntype=%d\n",returntype);
987  myexit(924636);
988  break;
989  }
990 
991 }
992 
993 
994 void UtoU_evolve2diag(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
995 {
996  void UtoU_gen(int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
997  int pl,pliter;
998 
999 #if(WHICHEOM==WITHGDET)
1000  // then UEVOLVE and UDIAG have same geometry (geom.g)
1001  PALLLOOP(pl) Uout[pl]=Uin[pl];
1002 #else
1003  UtoU_gen(ISMAANDEM, inputtype, returntype, ptrgeom, Uin, Uout);
1004 #endif
1005 
1006 }
1007 
1008 
1009 void UtoU(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1010 {
1011  void UtoU_gen(int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1012 
1013  UtoU_gen(ISMAANDEM, inputtype, returntype, ptrgeom, Uin, Uout);
1014 
1015 }
1016 
1017 void UtoU_ma(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1018 {
1019  void UtoU_gen(int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1020 
1021  UtoU_gen(ISMAONLY, inputtype, returntype, ptrgeom, Uin, Uout);
1022 
1023 }
1024 
1025 void UtoU_rad(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1026 {
1027  void UtoU_gen(int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1028 
1029  UtoU_gen(ISRADONLY, inputtype, returntype, ptrgeom, Uin, Uout);
1030 
1031 }
1032 
1033 void UtoU_em(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1034 {
1035  void UtoU_gen(int whichmaem, int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1036 
1037  UtoU_gen(ISEMONLY, inputtype, returntype, ptrgeom, Uin, Uout);
1038 
1039 }
1040 
1041 
1042 void UtoU_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1043 {
1044  void UtoU_gen_fromunothing(int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1045 
1046  UtoU_gen_fromunothing(ISMAANDEM, returntype, ptrgeom, Uin, Uout);
1047 
1048 }
1049 
1050 void UtoU_ma_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1051 {
1052  void UtoU_gen_fromunothing(int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1053 
1054  UtoU_gen_fromunothing(ISMAONLY, returntype, ptrgeom, Uin, Uout);
1055 
1056 }
1057 
1058 void UtoU_rad_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1059 {
1060  void UtoU_gen_fromunothing(int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1061 
1062  UtoU_gen_fromunothing(ISRADONLY, returntype, ptrgeom, Uin, Uout);
1063 
1064 }
1065 
1066 void UtoU_em_fromunothing(int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout)
1067 {
1068  void UtoU_gen_fromunothing(int whichmaem, int returntype,struct of_geom *ptrgeom,FTYPE *Uin, FTYPE *Uout);
1069 
1070  UtoU_gen_fromunothing(ISEMONLY, returntype, ptrgeom, Uin, Uout);
1071 
1072 }
1073 
1074 
1075 
1081 void PtoP(int inputtype, int returntype,struct of_geom *ptrgeom,FTYPE *pin, FTYPE *pout)
1082 {
1083  VARSTATIC FTYPE pstandard[NPR];
1084  VARSTATIC int pl,pliter;
1085 
1086 
1087 
1088 }
1089 
1090 
1092 void bcon_calc(FTYPE *pr, FTYPE *ucon, FTYPE *ucov, FTYPE *bcon)
1093 {
1094  VARSTATIC int j;
1095 
1096  bcon[TT] = pr[B1] * ucov[1] + pr[B2] * ucov[2] + pr[B3] * ucov[3];
1097  for (j = 1; j <= 3; j++)
1098  bcon[j] = (pr[B1 - 1 + j] + bcon[TT] * ucon[j]) / ucon[TT];
1099 
1100  return;
1101 }
1102 
1104 void Bcon_calc(struct of_state *q, FTYPE*B)
1105 {
1106  VARSTATIC FTYPE uu0,uu1,uu2,uu3;
1107  VARSTATIC FTYPE ud0,ud1,ud2,ud3;
1108  VARSTATIC FTYPE bu1,bu2,bu3;
1109  VARSTATIC FTYPE denom;
1110 
1111 
1112  uu0=q->ucon[TT];
1113  uu1=q->ucon[RR];
1114  uu2=q->ucon[TH];
1115  uu3=q->ucon[PH];
1116 
1117  ud0=q->ucov[TT];
1118  ud1=q->ucov[RR];
1119  ud2=q->ucov[TH];
1120  ud3=q->ucov[PH];
1121 
1122  bu1=q->bcon[RR];
1123  bu2=q->bcon[TH];
1124  bu3=q->bcon[PH];
1125 
1126  denom=1.0/(1.0+ud1*uu1+ud2*uu2+ud3*uu3);
1127 
1128  B[1]=uu0*(-(bu2*ud2+bu3*ud3)*uu1+bu1*(1.0+ud2*uu2+ud3*uu3))*denom;
1129  B[2]=uu0*(-(bu1*ud1+bu3*ud3)*uu2+bu2*(1.0+ud1*uu1+ud3*uu3))*denom;
1130  B[3]=uu0*(-(bu2*ud2+bu2*ud2)*uu3+bu3*(1.0+ud2*uu2+ud1*uu1))*denom;
1131 
1132 
1133 }
1134 
1135 
1137 void vbtopr(FTYPE *vcon,FTYPE *bcon,struct of_geom *geom, FTYPE *pr)
1138 {
1139  void Bcon_calc(struct of_state *q, FTYPE*B);
1140  VARSTATIC int pl,pliter;
1141  VARSTATIC struct of_state q;
1142  VARSTATIC FTYPE prim[NPR];
1144 
1145 
1146  // go ahead and get pr velocity
1147  PLOOP(pliter,pl) prim[pl]=0.0;
1148  prim[U1]=vcon[1];
1149  prim[U2]=vcon[2];
1150  prim[U3]=vcon[3];
1151 
1152  // vcon2pr(WHICHVEL,vcon,geom,pr); // need u^\mu, so do below instead
1153  ucon_calc_3vel(prim,geom,q.ucon,q.others);
1154  ucon2pr(WHICHVEL,q.ucon,geom,pr); // fills pr[U1->U3]
1155 
1156  // q.ucon[TT]=ucon[TT];
1157  // q.ucon[RR]=ucon[RR];
1158  // q.ucon[TH]=ucon[TH];
1159  // q.ucon[PH]=ucon[PH];
1160 
1161  lower_vec(q.ucon,geom,q.ucov);
1162 
1163  // q.bcon[TT]=bcon[TT]; // not used below
1164  q.bcon[RR]=bcon[RR];
1165  q.bcon[TH]=bcon[TH];
1166  q.bcon[PH]=bcon[PH];
1167 
1168  Bcon_calc(&q,&pr[B1-1]); // &pr[B1-1] since Bcon_calc() fills 1-3
1169 
1170 
1171 
1172 }
1173 
1174 
1175 
1176 
1177 
1180 void mhd_calc(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs)
1181 {
1182  void mhd_calc_0(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs);
1183  void mhd_calc_norestmass(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs);
1184 
1185 #if(REMOVERESTMASSFROMUU==2)
1186  mhd_calc_norestmass(pr, dir, geom, q, mhd, mhdabs);
1187 #else
1188  mhd_calc_0(pr, dir, geom, q, mhd, mhdabs);
1189 #endif
1190 
1191 }
1192 
1196 void mhd_calc_ma(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs)
1197 {
1198  void mhd_calc_0_ma(FTYPE *pr, int dir, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs);
1199  void mhd_calc_norestmass_ma(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs);
1200 
1201 #if(REMOVERESTMASSFROMUU==2)
1202  mhd_calc_norestmass_ma(pr, dir, geom, q, mhd, mhdabs, mhddiagpress, mhddiagpressabs);
1203 #else
1204  mhd_calc_0_ma(pr, dir, q, mhd, mhdabs, mhddiagpress, mhddiagpressabs);
1205 #endif
1206 
1207 }
1208 
1211 void mhd_calc_em(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs)
1212 {
1213  void mhd_calc_0_em(FTYPE *pr, int dir, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs);
1214  void mhd_calc_primfield_em(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs);
1215 
1216 #if(MAXWELL==GENMAXWELL)
1217  mhd_calc_0_em(pr, dir, q, mhd, mhdabs);
1218 #elif(MAXWELL==PRIMMAXWELL)
1219  mhd_calc_primfield_em(pr, dir, geom, q, mhd, mhdabs);
1220 #else
1221 #error No such MAXWELL
1222 #endif
1223 
1224 
1225 #if(DEBUGNSBH)
1226  // DEBUG:
1227  if(geom->i==26 && geom->j==40 && dir==1){
1228  dualfprintf(fail_file,"INEM1: ucondir=%21.15g %21.15g\n",q->ucon[dir],mhd[3]);
1229  }
1230 #endif
1231 
1232 
1233 
1234 }
1235 
1236 
1238 void mhd_calc_0(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs)
1239 {
1240  void mhd_calc_0_ma(FTYPE *pr, int dir, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs);
1241  void mhd_calc_em(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs);
1242  VARSTATIC int j;
1243  VARSTATIC FTYPE mhdma[NDIM],mhdem[NDIM];
1244  VARSTATIC FTYPE mhdmaabs[NDIM],mhdemabs[NDIM];
1245  VARSTATIC FTYPE mhddiagpress[NDIM];
1246  VARSTATIC FTYPE mhddiagpressabs[NDIM];
1247 
1248 
1249  mhd_calc_0_ma(pr, dir, q, mhdma, mhdmaabs, mhddiagpress, mhddiagpressabs);
1250  mhd_calc_em(pr, dir, geom, q, mhdem, mhdemabs);
1251 
1252 
1253  // add up MA+EM (no RAD here in T because R kept as separate fluid)
1254  DLOOPA(j) mhd[j] = (mhdma[j] + mhddiagpress[j]) + mhdem[j];
1255  if(mhdabs!=NULL) DLOOPA(j) mhdabs[j] = (mhdmaabs[j] + mhddiagpressabs[j]) + mhdemabs[j];
1256 
1257 }
1258 
1259 
1260 
1262 void mhd_calc_0_ma(FTYPE *pr, int dir, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs)
1263 {
1264  VARSTATIC int j;
1265  VARSTATIC FTYPE rho, u, P, w, eta, ptot;
1266 
1267  // below allows other scalars to be advected but not affect the stress-energy equations of motion
1268 #if(DOEVOLVERHO)
1269  rho = pr[RHO];
1270 #else
1271  rho = 0.0;
1272 #endif
1273 
1274 #if(DOEVOLVEUU)
1275  u = pr[UU];
1276  P = q->pressure;
1277 #else
1278  u = P = 0.0;
1279 #endif
1280 
1281  w = P + rho + u;
1282  eta = w;
1283  ptot = P;
1284 
1285  /* single row of mhd stress tensor, first index up, second index down
1286  */
1287  // mhd^{dir}_{j} =
1288  // j=0..3
1289  DLOOPA(j) mhd[j] = eta * q->ucon[dir] * q->ucov[j];
1290  if(mhdabs!=NULL) DLOOPA(j) mhdabs[j] = fabs(mhd[j]);
1291 
1292  if(mhddiagpress!=NULL) DLOOPA(j) mhddiagpress[j] = 0.0;
1293 #if(SPLITPRESSURETERMINFLUXMA==0)
1294  mhd[dir] += ptot;
1295  if(mhdabs!=NULL) mhdabs[dir] += fabs(ptot);
1296 #else
1297  // below equivalent to ptot * delta(dir,j)
1298  if(mhddiagpress!=NULL) mhddiagpress[dir] = ptot; // NOTEMARK: assumes if here, then mdhdiagpress better not be NULL
1299  if(mhddiagpressabs!=NULL) mhddiagpressabs[dir] = fabs(ptot);
1300 #endif
1301 
1302 }
1303 
1304 
1306 void mhd_calc_0_em(FTYPE *pr, int dir, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs)
1307 {
1308  VARSTATIC int j;
1309  VARSTATIC FTYPE r, u, P, w, bsq, eta, ptot;
1310 
1311  bsq = dot(q->bcon, q->bcov);
1312  eta = bsq;
1313  ptot = bsq*0.5;
1314 
1315  /* single row of mhd stress tensor, first index up, second index down
1316  */
1317  // mhd^{dir}_{j} =
1318  // j=0..3
1319  // DLOOPA(j) mhd[j] = eta * q->ucon[dir] * q->ucov[j] + ptot * delta(dir, j) - q->bcon[dir] * q->bcov[j];
1320  DLOOPA(j) mhd[j] = eta * q->ucon[dir] * q->ucov[j] - q->bcon[dir] * q->bcov[j];
1321  if(mhdabs!=NULL) DLOOPA(j) mhdabs[j] = fabs(mhd[j]);
1322  mhd[dir] += ptot;
1323  if(mhdabs!=NULL) mhdabs[dir] += fabs(ptot);
1324 
1325 }
1326 
1327 
1333 void mhd_calc_norestmass(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs)
1334 {
1335  void mhd_calc_norestmass_ma(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhdma, FTYPE *mhdmaabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs);
1336  void mhd_calc_em(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhdem, FTYPE *mhdemabs);
1337  VARSTATIC FTYPE mhdma[NDIM];
1338  VARSTATIC FTYPE mhdem[NDIM];
1339  VARSTATIC FTYPE mhdmaabs[NDIM];
1340  VARSTATIC FTYPE mhdemabs[NDIM];
1341  VARSTATIC int j;
1342  VARSTATIC FTYPE mhddiagpress[NDIM];
1343  VARSTATIC FTYPE mhddiagpressabs[NDIM];
1344 
1345  mhd_calc_norestmass_ma(pr, dir, geom, q, mhdma, mhdmaabs, mhddiagpress, mhddiagpressabs);
1346  mhd_calc_em(pr, dir, geom, q, mhdem, mhdemabs);
1347 
1348  // add up MA and RAD and EM parts
1349  DLOOPA(j) mhd[j] = (mhdma[j] + mhddiagpress[j]) + mhdem[j];
1350 
1351  if(mhdabs!=NULL) DLOOPA(j) mhdabs[j] = (mhdmaabs[j] + mhddiagpressabs[j]) + mhdemabs[j];
1352 
1353 }
1354 
1355 
1356 
1362 void mhd_calc_norestmass_ma(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs, FTYPE *mhddiagpress, FTYPE *mhddiagpressabs)
1363 {
1364  VARSTATIC int j;
1365  VARSTATIC FTYPE rho, u, P, w, bsq, eta, ptot;
1366 
1367 
1369  //
1370  // Hydro part
1371  //
1373 
1374  // below allows other scalars to be advected but not affect the stress-energy equations of motion
1375 #if(DOEVOLVERHO)
1376  rho = pr[RHO];
1377 #else
1378  rho = 0.0;
1379 #endif
1380 
1381 #if(DOEVOLVEUU)
1382  u = pr[UU];
1383  P = q->pressure;
1384 #else
1385  u = P = 0.0;
1386 #endif
1387 
1388  w = P + rho + u;
1389  eta = w;
1390  ptot = P;
1391 
1392 
1393 
1394  /* single row of mhd stress tensor, first index up, second index down
1395  */
1396  // mhd^{dir}_{j} =
1397  // j=0..3
1398  // eta u^dir u_j + rho u^dir = (p+u+b^2) u^dir u_j + rho u^dir u_j + rho u^dir
1399  // = (p+u+b^2) u^dir u_j + rho u^dir (u_j + 1)
1400 
1401  if(mhddiagpress!=NULL) DLOOPA(j) mhddiagpress[j] = 0.0;
1402  if(mhddiagpressabs!=NULL) DLOOPA(j) mhddiagpressabs[j] = 0.0;
1403 
1404  // T^dir_0
1405  j=0;
1406  FTYPE term1,term2;
1407  term1 = (P+u) * q->ucon[dir] *q->ucov[j];
1408  term2 = rho * q->ucon[dir] * q->ifremoverestplus1ud0elseud0;
1409  mhd[j] = term1 + term2 ;
1410  if(mhdabs!=NULL) mhdabs[j] = fabs(term1) + fabs(term2) ;
1411 
1412  // T^dir_j
1413  SLOOPA(j) mhd[j] = eta * q->ucon[dir] * q->ucov[j];
1414  if(mhdabs!=NULL) SLOOPA(j) mhdabs[j] = fabs(mhd[j]);
1415 
1416 #if(SPLITPRESSURETERMINFLUXMA==0)
1417  // below equivalent to ptot * delta(dir,j)
1418  mhd[dir] += ptot;
1419  if(mhdabs!=NULL) mhdabs[dir] += fabs(ptot);
1420 #else
1421  // below equivalent to ptot * delta(dir,j)
1422  if(mhddiagpress!=NULL) mhddiagpress[dir] = ptot; // NOTEMARK: assume mhddiagpress!=NULL if here
1423  if(mhddiagpressabs!=NULL) mhddiagpressabs[dir] = fabs(ptot);
1424 #endif
1425 
1426 
1427 #if(DEBUGNSBH)
1428  // DEBUG:
1429  if(geom->i==26 && geom->j==40 && dir==1){
1430  dualfprintf(fail_file,"INMA: ucondir=%21.15g %21.15g\n",q->ucon[dir],mhd[3]);
1431  }
1432 #endif
1433 
1434 
1435 }
1436 
1437 
1438 
1445 void mhd_calc_primfield_em(FTYPE *pr, int dir, struct of_geom *geom, struct of_state *q, FTYPE *mhd, FTYPE *mhdabs)
1446 {
1447  int Mcon_calc(FTYPE *pr, struct of_state *q, FTYPE (*Mcon)[NDIM]);
1448  void ffdestresstensor_dir(int dir, FTYPE (*Mcon)[NDIM], struct of_geom *geom, FTYPE *TEMdir);
1449  VARSTATIC FTYPE Mcon[NDIM][NDIM];
1450  VARSTATIC FTYPE TEMdir[NDIM];
1451  int mu;
1452  FTYPE Bsq,udotB,Bcon[NDIM],Bcov[NDIM],oneovergammasq;
1453  int jj,kk;
1454 
1456  //
1457  // Electrommagnetic part
1458  //
1460  // gives \dF^{\mu \nu}
1461 
1462 #if(0) // old way
1463  // GODMARK: need full Mcon to get partial TEM -- can one optimize this?
1464  Mcon_calc(pr, q, Mcon);
1465 
1466  // gives T^dir_\mu
1467  ffdestresstensor_dir(dir, Mcon, geom, mhd);
1468 #else
1469  // optimization that still avoids cancellation issue
1470 
1471  // T^\mu_\nu[EM] = b^2 u^\mu u_\nu - b^\mu b_\nu + (b^2/2)\delta^\mu_\nu
1472  // b^\mu = P^\mu_\nu B^\nu\gamma ; \gamma = -\eta.u where here \eta={-1,0,0,0} so \gamma=u^t
1473  // b^2 = (B^2 + (udotB)^2)/\gamma^2
1474  // --> 2 terms cancel
1475  // T^\mu_\nu = { B^2 u^\mu u_\nu - B^\mu B_\nu - udotB [ B^\mu u_\nu + B_\nu u^\mu] + (1/2)\delta^\mu_\nu[B^2 + udotB^2] }/\gamma^2
1476 
1477 
1478  // set B^\mu
1479  Bcon[TT]=0.0; SLOOPA(jj) Bcon[jj] = pr[B1+jj-1];
1480 
1481  // Get B_\mu = B^i g_{\mu i}
1482  DLOOPA(jj){
1483  Bcov[jj] = 0.0;
1484  SLOOPA(kk) Bcov[jj] += Bcon[kk]*(geom->gcov[GIND(jj,kk)]);
1485  }
1486  Bsq=0.0; SLOOPA(kk) Bsq += Bcon[kk]*Bcov[kk]; // B^i B_i
1487  udotB=0.0; SLOOPA(kk) udotB += Bcon[kk]*(q->ucov[kk]); // B^i u_i
1488 
1489 
1490  // T^dir_\mu, where dir is fixed and mu varies
1491  DLOOPA(mu) mhd[mu] = ( Bsq*(q->ucon[dir])*(q->ucov[mu]) - Bcon[dir]*Bcov[mu] - udotB*(Bcon[dir]*(q->ucov[mu]) + Bcov[mu]*(q->ucon[dir])) );
1492  // \delta^dir_\mu term:
1493  mhd[dir] += 0.5*(Bsq + udotB*udotB);
1494 
1495  oneovergammasq=1.0/((q->ucon[TT])*(q->ucon[TT]));
1496 
1497  DLOOPA(mu) mhd[mu] *= oneovergammasq ;
1498 
1499 #endif
1500 
1501 
1502  if(mhdabs!=NULL) DLOOPA(mu) mhdabs[mu] = fabs(mhd[mu]);
1503 
1504 
1505 
1506 #if(DEBUGNSBH)
1507  // DEBUG:
1508  if(geom->i==26 && geom->j==40 && dir==1){
1509  dualfprintf(fail_file,"INEM2: ucondir=%21.15g Bcondir=%21.15g (%21.15g %21.15g %21.15g) mhd3=%21.15g\n",q->ucon[dir],Bcon[dir],Bsq,udotB,oneovergammasq,mhd[3]);
1510  DLOOPA(mu) dualfprintf(fail_file,"mu=%d ucov[mu]=%21.15g Bcov[mu]=%21.15g\n",mu,q->ucov[mu],Bcov[mu]);
1511  }
1512 #endif
1513 
1514 
1515 }
1516 
1517 
1518 
1519 
1522 void compute_1plusud0_old(FTYPE *pr, struct of_geom *geom, struct of_state *q, FTYPE *plus1ud0)
1523 {
1524  int j,k;
1525  FTYPE plus1gv00;
1526  FTYPE AA,BB,alpha;
1527  FTYPE vcon[NDIM];
1528 
1529  // 3-velocity in coordinate basis
1530  SLOOPA(j) vcon[j]=q->ucon[j]/q->ucon[TT];
1531 
1532  // plus1gv00=1.0+geom->gcov[GIND(TT,TT)];
1533  plus1gv00=geom->gcovpert[TT];
1534 
1535  AA=0.0;
1536  SLOOPA(j) AA+=2.0*geom->gcov[GIND(TT,j)]*vcon[j];
1537  SLOOP(j,k) AA+=geom->gcov[GIND(j,k)]*vcon[j]*vcon[k];
1538  //AA/=geom->gcov[GIND(TT,TT)];
1539  BB=geom->gcov[GIND(TT,TT)];
1540 
1541  alpha=0.0;
1542  SLOOPA(j) alpha+=geom->gcov[GIND(j,TT)]*q->ucon[j];
1543 
1544  // *plus1ud0=(plus1gv00+(2.0*alpha+alpha*alpha)*(1.0+AA)+AA)/((1.0+alpha)*(1.0+AA)+sqrt(-geom->gcov[GIND(TT,TT)]*(1.0+AA)));
1545 
1546  *plus1ud0=(plus1gv00*BB+(2.0*alpha+alpha*alpha)*(BB+AA)+AA)/((1.0+alpha)*(BB+AA)+BB*sqrt(-(BB+AA)));
1547 
1548 }
1549 
1555 void compute_1plusud0_general(FTYPE *pr, struct of_geom *geom, struct of_state *q, FTYPE *plus1ud0)
1556 {
1557  VARSTATIC int j,k;
1558  VARSTATIC FTYPE plus1gv00;
1559  VARSTATIC FTYPE vsq,gvtt,alpha;
1560  VARSTATIC FTYPE vcon[NDIM];
1561  VARSTATIC FTYPE uu0;
1562 
1563 
1564  // 3-velocity in coordinate basis
1565  SLOOPA(j) vcon[j]=q->ucon[j]/q->ucon[TT];
1566 
1567  // plus1gv00=1.0+geom->gcov[GIND(TT,TT)];
1568  plus1gv00=geom->gcovpert[TT];
1569 
1570  vsq=geom->gcovpert[TT];
1571  SLOOPA(j) vsq+=2.0*geom->gcov[GIND(TT,j)]*vcon[j];
1572  SLOOP(j,k) vsq+=geom->gcov[GIND(j,k)]*vcon[j]*vcon[k];
1573 
1574  gvtt=geom->gcov[GIND(TT,TT)];
1575 
1576  alpha=0.0;
1577  SLOOPA(j) alpha+=geom->gcov[GIND(j,TT)]*q->ucon[j];
1578 
1579  uu0 = q->ucon[TT];
1580 
1581  *plus1ud0=alpha + ((1.0-gvtt)*plus1gv00 - uu0*uu0*vsq*gvtt*gvtt)/(1.0-gvtt*uu0);
1582 
1583  // dualfprintf(fail_file,"%g %g %g : wrong: %g\n",alpha,plus1gv00,gvtt,*plus1ud0);
1584 
1585  // *plus1ud0=1.0+q->ucov[TT];
1586 
1587  // dualfprintf(fail_file,"right: %g\n",*plus1ud0);
1588 
1589 }
1590 
1591 
1593 void compute_1plusud0_rel4vel(FTYPE *pr, struct of_geom *geom, struct of_state *q, FTYPE *plus1ud0)
1594 {
1595  VARSTATIC int j,k;
1596  VARSTATIC FTYPE ud0tilde,alpha,alphasq;
1597  VARSTATIC FTYPE gamma,qsq;
1598 
1599  // from q->others[] only generated for WHICHVEL=REL4VEL
1600  gamma=q->others[OTHERGAMMA];
1601  qsq=q->others[OTHERQSQ];
1602 
1603 
1604  // \tilde{u}_t = \tilde{u}^i g_{ti} since \tilde{u}^t=0
1605  ud0tilde = 0.0;
1606  SLOOPA(j) ud0tilde += pr[U1+j-1]*(geom->gcov[GIND(TT,j)]);
1607 
1608  alpha = geom->alphalapse;
1609  alphasq = alpha*alpha;
1610 
1611  *plus1ud0 = ud0tilde + (geom->gcovpert[TT] - alphasq*( (geom->betasqoalphasq) + qsq))/(1.0+gamma*alpha);
1612 
1613 }
1614 
1615 
1619 int source(FTYPE *pi, FTYPE *pr, FTYPE *pf, int *didreturnpf, int *eomtype, struct of_geom *ptrgeom, struct of_state *q, FTYPE *ui, FTYPE *uf, FTYPE *CUf, FTYPE *CUimp, FTYPE dissmeasure, FTYPE *dUriemann, FTYPE (*dUcomp)[NPR], FTYPE *dU)
1620 {
1621  // double (*)[8]
1622  VARSTATIC int i,j,sc;
1623  VARSTATIC int pl,pliter;
1624  int source_conn(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q,FTYPE *dU);
1625  VARSTATIC FTYPE dUother[NPR];
1626  VARSTATIC FTYPE Ugeomfreei[NPR],Ugeomfreef[NPR];
1627 
1628 
1630  // initialize source terms to be zero
1632  PLOOP(pliter,pl){
1633  SCLOOP(sc) dUcomp[sc][pl] = 0.;
1634  dU[pl] = 0.;
1635  }
1636 
1637 #if(SPLITNPR)
1638 #if((WHICHEOM==WITHNOGDET)&&(NOGDETB1>0)||(NOGDETB2>0)||(NOGDETB3>0))
1639 #error Not correct SPLITNPR use#1
1640 #endif
1641  // if only doing B1-B3, then assume no source term for magnetic field
1642  if(nprlist[nprstart]==B1 && nprlist[nprend]==B3) return(0);
1643 #endif
1644 
1645 
1646 
1648  //
1649  // First get geometry source (already does contain geometry prefactor term)
1650  // KORALTODO: Should I use dUriemann to already update p(U) and q(p) for more accurate geometry?
1651  source_conn(pr,ptrgeom, q, dUcomp[GEOMSOURCE]);
1652 
1653 
1655  //
1656  // Second get physics source terms (using dUother for constraint)
1657  // get update pre- additional physics
1658  // Assumes all quantities are at cell centers
1659  PLOOP(pliter,pl){
1660  dUother[pl] = (dUriemann[pl] + dUcomp[GEOMSOURCE][pl])*(ptrgeom->IEOMFUNCNOSINGMAC(pl)); // remove geometry factor for dUother
1661  // ui is current timestep's ui.
1662  Ugeomfreei[pl] = ui[pl]*(ptrgeom->IEOMFUNCNOSINGMAC(pl)); // expect ui to be UEVOLVE form
1663  // uf is "previous" timestep's uf, which is not generally ui for arbitrary RK methods, and should not include dUother, etc.
1664  Ugeomfreef[pl] = uf[pl]*(ptrgeom->IEOMFUNCNOSINGMAC(pl)); // expect uf to be UEVOLVE form
1665  }
1666 
1667  if(FLUXB==FLUXCTSTAG){
1668  // if staggered field, then ui and uf are staggered field locations, but for *physics* processes, we want to assume all at same location, so send in physical version
1669  // this overwrites above assignments
1670  PLOOPBONLY(pl){
1671  // assume already got field update in advance_standard() [as opposed to advance_standard_orig()] and no geometry for field as required for that method.
1672  // but want to be able to have Ui by itself mean no changes, so that's pr. Uf is only used in some RK methods, that can be pf. But then want dUother to be so that when using IFSET() with full dt that get pf
1673  // Ugeomfreei[pl]=pi[pl]; // unnecessary
1674  // Ugeomfreef[pl]=pf[pl]; // No, should stay as from uf as *previous* timestep's Uf, so that RK3/4 are consistent with below.
1675  // KORALTODO SUPERGODMARK: This means need advance.c source() to have uf as previous field uf, not updated uf from dUriemann *and* not tempucum for finalstep=1
1676  dUother[pl]=dUfromUFSET(CUf,dt,Ugeomfreei[pl],Ugeomfreef[pl],pf[pl]);
1677  // Also, update "guess" pr with new field, since pr is used as default guess and want field to be correct. So pr is no longer what computed flux.
1678  // pr[pl]=pf[pl]; // only for implicit schemes, and handle this inside koral_source_rad_implicit() now.
1679  }
1680  // now sourcephysics() call will have all CENT quantities
1681  }
1682 
1683  sourcephysics(pi, pr, pf, didreturnpf, eomtype, ptrgeom, q, Ugeomfreei, Ugeomfreef, CUf, CUimp, dissmeasure, dUother, dUcomp);
1684 
1686  //
1687  // Third, deal with equation of motion factors that don't depend upon any additional physics
1688  // don't add geometry prefactor onto geometry source since already has it -- only add to additional physics terms
1689  SCPHYSICSLOOP(sc) PLOOP(pliter,pl) dUcomp[sc][pl] *= ptrgeom->EOMFUNCMAC(pl);
1690 
1691 
1693  //
1694  // Fourth, compute total since that's all the evolution cares about (comp left just for diagnostics).
1695  SCLOOP(sc) PLOOP(pliter,pl) dU[pl]+=dUcomp[sc][pl];
1696 
1697 
1698 
1699  // done!
1700  return (0);
1701 }
1702 
1703 
1704 
1706 int bsq_calc_general(FTYPE *pr, struct of_geom *ptrgeom, FTYPE *bsq)
1707 {
1708  VARSTATIC struct of_state q;
1709 
1710  MYFUN(get_state(pr, ptrgeom, &q) ,"phys.c:bsq_calc()", "get_state() dir=0", 1);
1711  *bsq = dot(q.bcon, q.bcov);
1712  return (0);
1713 }
1714 
1716 int bsq_calc_fromq_general(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq)
1717 {
1718 
1719  *bsq = dot(q->bcon, q->bcov);
1720 
1721  return (0);
1722 }
1723 
1725 int bsq_calc_rel4vel(FTYPE *pr, struct of_geom *ptrgeom, FTYPE *bsq)
1726 {
1727  VARSTATIC struct of_state q;
1728  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1729  int bsq_calc_fromq_rel4vel(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
1730 
1731 
1732  MYFUN(get_state_uconucovonly(pr, ptrgeom, &q) ,"phys.c:bsq_calc()", "get_state_uconucovonly() dir=0", 1);
1733 
1734  bsq_calc_fromq_rel4vel(pr, ptrgeom, &q, bsq);
1735 
1736  return (0);
1737 }
1738 
1739 
1740 int bsq_calc_fromq_rel4vel(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq)
1741 {
1742  FTYPE Bsq,udotB,Bcon[NDIM],Bcov[NDIM],oneovergammasq;
1743  int jj,kk;
1744 
1745  // set B^\mu
1746  Bcon[TT]=0.0; SLOOPA(jj) Bcon[jj] = pr[B1+jj-1];
1747 
1748  // Get B_\mu = B^i g_{\mu i}
1749  DLOOPA(jj){
1750  Bcov[jj] = 0.0;
1751  SLOOPA(kk) Bcov[jj] += Bcon[kk]*(ptrgeom->gcov[GIND(jj,kk)]);
1752  }
1753  Bsq=0.0; SLOOPA(kk) Bsq += Bcon[kk]*Bcov[kk]; // B^i B_i
1754  udotB=0.0; SLOOPA(kk) udotB += Bcon[kk]*(q->ucov[kk]); // B^i u_i
1755 
1756  *bsq = (Bsq + udotB*udotB);
1757 
1758  oneovergammasq=1.0/((q->ucon[TT])*(q->ucon[TT]));
1759 
1760  *bsq *= oneovergammasq;
1761 
1762  return(0);
1763 }
1764 
1765 
1766 
1767 
1768 
1769 void lower_vec(FTYPE *ucon, struct of_geom *geom, FTYPE *ucov)
1770 {
1771  ucov[0] = geom->gcov[GIND(0,0)]*ucon[0]
1772  + geom->gcov[GIND(0,1)]*ucon[1]
1773  + geom->gcov[GIND(0,2)]*ucon[2]
1774  + geom->gcov[GIND(0,3)]*ucon[3] ;
1775  ucov[1] = geom->gcov[GIND(0,1)]*ucon[0]
1776  + geom->gcov[GIND(1,1)]*ucon[1]
1777  + geom->gcov[GIND(1,2)]*ucon[2]
1778  + geom->gcov[GIND(1,3)]*ucon[3]
1779  ;
1780  ucov[2] = geom->gcov[GIND(0,2)]*ucon[0]
1781  + geom->gcov[GIND(1,2)]*ucon[1]
1782  + geom->gcov[GIND(2,2)]*ucon[2]
1783 #if(DOMIXTHETAPHI)
1784  + geom->gcov[GIND(2,3)]*ucon[3]
1785 #endif
1786  ;
1787  ucov[3] = geom->gcov[GIND(0,3)]*ucon[0]
1788  + geom->gcov[GIND(1,3)]*ucon[1]
1789 #if(DOMIXTHETAPHI)
1790  + geom->gcov[GIND(2,3)]*ucon[2]
1791 #endif
1792  + geom->gcov[GIND(3,3)]*ucon[3] ;
1793 
1794  return ;
1795 }
1796 
1797 void lowerf(FTYPE *fcon, struct of_geom *geom, FTYPE *fcov)
1798 {
1799  VARSTATIC int j,k;
1800  VARSTATIC int jp,kp;
1801  VARSTATIC FTYPE myfcon[NDIM][NDIM],myfcov[NDIM][NDIM];
1802 
1803 
1804  myfcon[0][0]=myfcon[1][1]=myfcon[2][2]=myfcon[3][3]=0;
1805  myfcon[0][1]=fcon[0];
1806  myfcon[0][2]=fcon[1];
1807  myfcon[0][3]=fcon[2];
1808  myfcon[1][2]=fcon[3];
1809  myfcon[1][3]=fcon[4];
1810  myfcon[2][3]=fcon[5];
1811  //
1812  myfcon[1][0]=-fcon[0];
1813  myfcon[2][0]=-fcon[1];
1814  myfcon[3][0]=-fcon[2];
1815  myfcon[2][1]=-fcon[3];
1816  myfcon[3][1]=-fcon[4];
1817  myfcon[3][2]=-fcon[5];
1818 
1819  DLOOP(j,k){
1820  myfcov[j][k]=0;
1821  for(jp=0;jp<NDIM;jp++) for(kp=0;kp<NDIM;kp++){
1822  myfcov[j][k]+=myfcon[jp][kp]*geom->gcov[GIND(j,jp)]*geom->gcov[GIND(k,kp)];
1823  }
1824  }
1825  fcov[0]=myfcov[0][1];
1826  fcov[1]=myfcov[0][2];
1827  fcov[2]=myfcov[0][3];
1828  fcov[3]=myfcov[1][2];
1829  fcov[4]=myfcov[1][3];
1830  fcov[5]=myfcov[2][3];
1831 
1832  return ;
1833 }
1834 
1835 void raise_vec(FTYPE *ucov, struct of_geom *geom, FTYPE *ucon)
1836 {
1837 
1838  ucon[0] = geom->gcon[GIND(0,0)]*ucov[0]
1839  + geom->gcon[GIND(0,1)]*ucov[1]
1840  + geom->gcon[GIND(0,2)]*ucov[2]
1841  + geom->gcon[GIND(0,3)]*ucov[3] ;
1842  ucon[1] = geom->gcon[GIND(0,1)]*ucov[0]
1843  + geom->gcon[GIND(1,1)]*ucov[1]
1844  + geom->gcon[GIND(1,2)]*ucov[2]
1845  + geom->gcon[GIND(1,3)]*ucov[3] ;
1846  ucon[2] = geom->gcon[GIND(0,2)]*ucov[0]
1847  + geom->gcon[GIND(1,2)]*ucov[1]
1848  + geom->gcon[GIND(2,2)]*ucov[2]
1849  + geom->gcon[GIND(2,3)]*ucov[3] ;
1850  ucon[3] = geom->gcon[GIND(0,3)]*ucov[0]
1851  + geom->gcon[GIND(1,3)]*ucov[1]
1852  + geom->gcon[GIND(2,3)]*ucov[2]
1853  + geom->gcon[GIND(3,3)]*ucov[3] ;
1854 
1855  return ;
1856 }
1857 
1858 
1861 int get_state(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1862 {
1863  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1864  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1865  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1866  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
1867  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
1868 
1869 
1870  get_state_uconucovonly(pr, ptrgeom, q);
1871 
1872 #if(EOMRADTYPE!=EOMRADNONE)
1873  get_state_uradconuradcovonly(pr, ptrgeom, q);
1874 #endif
1875 
1876  get_state_bconbcovonly(pr, ptrgeom, q);
1877 
1878  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
1879 
1880  get_state_thermodynamics(1,ptrgeom, pr, q);
1881 
1882  return (0);
1883 }
1884 
1885 
1888 int get_state_radonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1889 {
1890  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1891 
1892 
1893 #if(EOMRADTYPE!=EOMRADNONE)
1894  get_state_uradconuradcovonly(pr, ptrgeom, q);
1895 #endif
1896  return (0);
1897 }
1898 
1901 int get_state_norad_part1(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1902 {
1903  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1904  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1905  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
1906 
1907 
1908  get_state_uconucovonly(pr, ptrgeom, q);
1909 
1910  get_state_bconbcovonly(pr, ptrgeom, q);
1911 
1912  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
1913 
1914  return (0);
1915 }
1916 
1919 int get_state_norad_part2(int needentropy, FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1920 {
1921  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
1922 
1923 
1924  get_state_thermodynamics(needentropy, ptrgeom, pr, q);
1925 
1926  return (0);
1927 }
1928 
1929 
1930 
1932 int get_state_nofield(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1933 {
1934  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1935  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1936  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
1937 
1938 
1939  get_state_uconucovonly(pr, ptrgeom, q);
1940 
1941 #if(EOMRADTYPE!=EOMRADNONE)
1942  get_state_uradconuradcovonly(pr, ptrgeom, q);
1943 #endif
1944 
1945  get_state_thermodynamics(1,ptrgeom, pr, q);
1946 
1947  return (0);
1948 }
1949 
1950 
1952 int get_stateforcheckinversion(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1953 {
1954  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1955  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1956  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1957  int get_state_thermodynamics_forcheckinversion(struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
1958  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
1959 
1960 
1961  get_state_uconucovonly(pr, ptrgeom, q);
1962 
1963 #if(EOMRADTYPE!=EOMRADNONE)
1964  get_state_uradconuradcovonly(pr, ptrgeom, q);
1965 #endif
1966 
1967  get_state_bconbcovonly(pr, ptrgeom, q);
1968 
1969  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
1970 
1972 
1973  return (0);
1974 }
1975 
1976 
1977 
1978 
1981 int pureget_stateforfluxcalc(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
1982 {
1983  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1984  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1985  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1986  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
1987  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
1988  int get_state_prims(FTYPE *pr, struct of_state *q);
1989  int get_state_geom(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1990  int get_state_Blower(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1991  int get_state_vcon_gdetBcon_overut(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1992 
1993 
1994 #if(MERGEDC2EA2CMETHOD)
1995  // only needed if doing merged method
1996  get_state_geom(pr, ptrgeom, q);
1997 
1998  get_state_prims(pr, q);
1999 
2000  get_state_Blower(pr, ptrgeom, q);
2001 #endif
2002 
2003  get_state_uconucovonly(pr, ptrgeom, q);
2004 
2005 #if(EOMRADTYPE!=EOMRADNONE)
2006  get_state_uradconuradcovonly(pr, ptrgeom, q);
2007 #endif
2008 
2009 #if(MERGEDC2EA2CMETHOD)
2010  get_state_vcon_gdetBcon_overut(pr, ptrgeom, q);
2011 #endif
2012 
2013 #if(COMPUTE4FIELDforFLUX)
2014  get_state_bconbcovonly(pr, ptrgeom, q);
2015 #endif
2016 
2017  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
2018 
2019  get_state_thermodynamics(1,ptrgeom, pr, q);
2020 
2021 
2022  return (0);
2023 }
2024 
2025 
2028 int pureget_stateforsource(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2029 {
2030  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2031  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2032  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2033  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
2034  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
2035 
2036 
2037  get_state_uconucovonly(pr, ptrgeom, q);
2038 
2039 #if(EOMRADTYPE!=EOMRADNONE)
2040  get_state_uradconuradcovonly(pr, ptrgeom, q);
2041 #endif
2042 
2043 
2044  // below needed for dUtodt() and compute_dt_fromsource()
2045 #if(COMPUTE4FIELDatALL)
2046  get_state_bconbcovonly(pr, ptrgeom, q);
2047 #endif
2048 
2049  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
2050 
2051  get_state_thermodynamics(1,ptrgeom, pr, q);
2052 
2053  return (0);
2054 }
2055 
2058 int pureget_stateforinterpline(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2059 {
2060  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2061  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2062  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2063  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
2064  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
2065 
2066 
2067  get_state_uconucovonly(pr, ptrgeom, q);
2068 
2069 #if(EOMRADTYPE!=EOMRADNONE)
2070  get_state_uradconuradcovonly(pr, ptrgeom, q);
2071 #endif
2072 
2073 #if(COMPUTE4FIELDatALL)
2074  get_state_bconbcovonly(pr, ptrgeom, q);
2075 #endif
2076 
2077  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
2078 
2079  get_state_thermodynamics(1,ptrgeom, pr, q);
2080 
2081  return (0);
2082 }
2083 
2086 int pureget_stateforglobalwavespeeds(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2087 {
2088  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2089  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2090  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2091  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
2092  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
2093 
2094 
2095  get_state_uconucovonly(pr, ptrgeom, q);
2096 
2097 #if(EOMRADTYPE!=EOMRADNONE)
2098  get_state_uradconuradcovonly(pr, ptrgeom, q);
2099 #endif
2100 
2101 #if(COMPUTE4FIELDatALL)
2102  get_state_bconbcovonly(pr, ptrgeom, q);
2103 #endif
2104 
2105  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
2106 
2107  get_state_thermodynamics(1,ptrgeom, pr, q);
2108 
2109  return (0);
2110 }
2111 
2114 int pureget_stateforfluxcalcorsource(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2115 {
2116  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2117  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2118  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2119  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
2120  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
2121  int get_state_prims(FTYPE *pr, struct of_state *q);
2122  int get_state_geom(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2123  int get_state_Blower(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2124  int get_state_vcon_gdetBcon_overut(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2125 
2126 
2127 #if(MERGEDC2EA2CMETHOD)
2128  // only needed if doing merged method
2129  get_state_geom(pr, ptrgeom, q);
2130 
2131  get_state_prims(pr, q);
2132 
2133  get_state_Blower(pr, ptrgeom, q);
2134 #endif
2135 
2136  get_state_uconucovonly(pr, ptrgeom, q);
2137 
2138 #if(EOMRADTYPE!=EOMRADNONE)
2139  get_state_uradconuradcovonly(pr, ptrgeom, q);
2140 #endif
2141 
2142 #if(MERGEDC2EA2CMETHOD)
2143  get_state_vcon_gdetBcon_overut(pr, ptrgeom, q);
2144 #endif
2145 
2146 #if(COMPUTE4FIELDatALL)
2147  get_state_bconbcovonly(pr, ptrgeom, q);
2148 #endif
2149 
2150  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
2151 
2152  get_state_thermodynamics(1,ptrgeom, pr, q);
2153 
2154 
2155  return (0);
2156 }
2157 
2158 
2159 
2162 int get_stateforUdiss(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2163 {
2164  int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2165  int get_state_uradconuradcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2166  int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
2167  int get_state_thermodynamics(int needentropy,struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q);
2168  int bsq_calc_fromq(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q, FTYPE *bsq);
2169 
2170 
2171  get_state_uconucovonly(pr, ptrgeom, q);
2172 
2173 #if(EOMRADTYPE!=EOMRADNONE)
2174  get_state_uradconuradcovonly(pr, ptrgeom, q);
2175 #endif
2176 
2177 #if(COMPUTE4FIELDatALL)
2178  get_state_bconbcovonly(pr, ptrgeom, q);
2179 #endif
2180 
2181  bsq_calc_fromq(pr,ptrgeom,q,&(q->bsq));
2182 
2183  get_state_thermodynamics(1,ptrgeom, pr, q);
2184 
2185 
2186  return (0);
2187 }
2188 
2189 
2190 
2192 int get_state_bconbcovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2193 {
2194 
2195  // b^\mu
2196  bcon_calc(pr, q->ucon, q->ucov, q->bcon);
2197  // b^\mu
2198  lower_vec(q->bcon, ptrgeom, q->bcov);
2199 
2200  return (0);
2201 }
2202 
2203 
2205 int get_state_uconucovonly(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2206 {
2207  void compute_1plusud0(FTYPE *pr, struct of_geom *geom, struct of_state *q, FTYPE *plus1ud0); // plus1ud0=(1+q->ucov[TT])
2208 
2209 
2210  // u^\mu
2211  MYFUN(ucon_calc(pr, ptrgeom, q->ucon,q->others) ,"phys.c:get_state()", "ucon_calc()", 1);
2212 
2213 
2214  // u_\mu
2215  lower_vec(q->ucon, ptrgeom, q->ucov);
2216 
2217 #if(REMOVERESTMASSFROMUU==1 || REMOVERESTMASSFROMUU==2)
2218 
2219 #if(UD0PLUS1FIX==0)
2220  q->ifremoverestplus1ud0elseud0=1.0+(q->ucov[TT]);
2221 #else
2222  compute_1plusud0(pr,ptrgeom,q,&(q->ifremoverestplus1ud0elseud0)); // plus1ud0=(1+q->ucov[TT])
2223 #endif
2224 
2225 #else
2227 #endif
2228 
2229  return (0);
2230 }
2231 
2232 
2233 
2234 
2236 int get_state_vcon_gdetBcon_overut(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2237 {
2238  int jj;
2239  FTYPE overut;
2240 
2241  overut=1.0/q->ucon[TT];
2242 
2243 #if(MERGEDC2EA2CMETHOD)
2244  q->overut=overut;
2245 
2246  q->vcon[TT]=1.0; SLOOPA(jj) q->vcon[jj]=q->ucon[jj]*overut;
2247 
2248  q->gdetBcon[TT]=0.0; SLOOPA(jj) q->gdetBcon[jj]=(q->prim[B1-1+jj])*(q->EOMFUNCMAC(B1-1+jj));
2249 #endif
2250 
2251  return (0);
2252 }
2253 
2254 
2255 
2257 int get_state_Blower(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2258 {
2259  int jj;
2260  FTYPE Bcon[NDIM];
2261 
2262  Bcon[TT]=0.0; SLOOPA(jj) Bcon[jj]=pr[B1-1+jj];
2263 
2264 #if(MERGEDC2EA2CMETHOD)
2265  // get B_\mu
2266  lower_vec(Bcon, ptrgeom, q->Blower);
2267 #endif
2268 
2269  return (0);
2270 }
2271 
2272 
2273 
2275 int get_state_thermodynamics(int needentropy, struct of_geom *ptrgeom, FTYPE *pr, struct of_state *q)
2276 {
2277 
2278  // does assume ptrgeom or something related set indices for advanced EOSs
2279  q->pressure = pressure_rho0_u_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pr[RHO],pr[UU]);
2280 
2281 #if(DOENTROPY!=DONOENTROPY)
2282  if(needentropy) entropy_calc(ptrgeom,pr,&(q->entropy));
2283 #endif
2284 
2285  return (0);
2286 
2287 }
2288 
2289 
2292 {
2293 
2294  // does assume ptrgeom or something related set indices for advanced EOSs
2295  q->pressure = pressure_rho0_u_simple_forcheckinversion(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pr[RHO],pr[UU]);
2296 
2297 #if(DOENTROPY!=DONOENTROPY)
2298  entropy_calc_forcheckinversion(ptrgeom,pr,&(q->entropy));
2299 #endif
2300 
2301  return (0);
2302 
2303 }
2304 
2306 int get_state_prims(FTYPE *pr, struct of_state *q)
2307 {
2308  int pl,pliter;
2309 
2310 #if(MERGEDC2EA2CMETHOD)
2311  // just copies
2312  PALLLOOP(pl) q->prim[pl] = pr[pl];
2313 #endif
2314 
2315  return (0);
2316 
2317 }
2318 
2320 int get_state_geom(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q)
2321 {
2322  int pl,pliter;
2323 
2324 #if(MERGEDC2EA2CMETHOD)
2325  q->gdet=ptrgeom->gdet;
2326  PALLLOOP(pl) q->EOMFUNCMAC(pl)=ptrgeom->EOMFUNCMAC(pl); // note that this used even if WITHEOM==WITHGDET
2327 #endif
2328 
2329  return (0);
2330 }
2331 
2332 
2334 int invertentropyflux_calc(struct of_geom *ptrgeom, FTYPE entropyflux,int dir, struct of_state *q, FTYPE *pr)
2335 {
2337 
2338  // get entropy [entropy can be any value]
2339  entropy=entropyflux/q->ucon[dir];
2340  ufromentropy_calc(ptrgeom, entropy, pr);
2341 
2342  return(0);
2343 }
2344 
2347 int ufromentropy_calc(struct of_geom *ptrgeom, FTYPE entropy, FTYPE *pr)
2348 {
2349 
2350  // entropy version of ie
2351  pr[ENTROPY]=compute_u_from_entropy_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pr[RHO],entropy);
2352 
2353  return(0);
2354 }
2355 
2356 
2361 {
2362  VARSTATIC FTYPE gamma;
2363  VARSTATIC FTYPE qsq;
2364  VARSTATIC int j ;
2365  int gamma_calc_fromuconrel(FTYPE *uconrel, struct of_geom *geom, FTYPE*gamma, FTYPE *qsq);
2366 
2367 
2368  MYFUN(gamma_calc_fromuconrel(uconrel,geom,&gamma,&qsq),"ucon_calc_rel4vel_fromuconrel: gamma_calc_fromuconrel failed\n","phys.c",1);
2369 
2370  // aux results
2371  others[OTHERGAMMA]=gamma;
2372  others[OTHERQSQ]=qsq;
2373 
2374  // alpha = 1./sqrt(-geom->gcon[GIND(TT,TT)]) ;
2375  ucon[TT] = gamma/(geom->alphalapse) ;
2376  // stored beta as well since otherwise have to use gcon and expensive to look that up from memory if cache-miss
2377  SLOOPA(j) ucon[j] = uconrel[j] - ucon[TT]*(geom->beta[j]);
2378 
2379  // hence v^j = uconrel^j/u^t - beta^j
2380 
2381  return(0) ;
2382 }
2383 
2384 
2387 int uconrel(FTYPE *ucon, FTYPE *uconrel, struct of_geom *geom)
2388 {
2389  VARSTATIC int j ;
2390 
2391  // stored beta as well since otherwise have to use gcon and expensive to look that up from memory if cache-miss
2392  SLOOPA(j) uconrel[j] = ucon[j] + ucon[TT]*(geom->beta[j]);
2393 
2394  // hence v^j = uconrel^j/u^t - beta^j
2395 
2396  return(0) ;
2397 }
2398 
2399 
2402 {
2404  VARSTATIC int j;
2405  int ucon_calc_rel4vel_fromuconrel(FTYPE *uconrel, struct of_geom *geom, FTYPE *ucon, FTYPE *others);
2406 
2407  uconrel[0]=0;
2408  uconrel[1]=pr[U1];
2409  uconrel[2]=pr[U2];
2410  uconrel[3]=pr[U3];
2411 
2412 
2413 
2414  // SLOOPA(j) dualfprintf(fail_file,"ucon_calc_rel4vel: uconrel[%d]=%21.15g\n",j,uconrel[j]); // CHANGINGMARK
2415 
2416  MYFUN(ucon_calc_rel4vel_fromuconrel(uconrel, geom, ucon, others),"ucon_calc_rel4vel: ucon_calc_rel4vel_fromuconrel failed\n","phys.c",1);
2417 
2418 
2419  return(0) ;
2420 }
2421 
2422 int ucon_calc_whichvel(int whichvel, FTYPE *pr, struct of_geom *geom, FTYPE *ucon, FTYPE *others)
2423 {
2424  if(whichvel==VEL4){
2425  return(ucon_calc_4vel(pr,geom,ucon,others));
2426  }
2427  else if(whichvel==VEL3){
2428  return(ucon_calc_3vel(pr,geom,ucon,others));
2429  }
2430  else if(whichvel==VELREL4){
2431  return(ucon_calc_rel4vel(pr,geom,ucon,others));
2432  }
2433  else{
2434  dualfprintf(fail_file,"No such whichvel=%d for ucon_calc_whichvel()\n",whichvel);
2435  myexit(384852);
2436  }
2437 
2438  return(1); // shouldn't get here
2439 
2440 }
2441 
2442 
2444 int gamma_calc(FTYPE *pr, struct of_geom *geom, FTYPE*gamma, FTYPE *qsq)
2445 {
2447  VARSTATIC int j;
2448  int gamma_calc_fromuconrel(FTYPE *uconrel, struct of_geom *geom, FTYPE*gamma, FTYPE *qsq);
2449 
2450 #if(WHICHVEL!=VELREL4)
2451  dualfprintf(fail_file,"gamma_calc() designed for WHICHVEL=VELREL4\n");
2452  myexit(77);
2453 #endif
2454 
2455  // assumes input pr is WHICHVEL=VELREL4
2456  uconrel[0]=0;
2457  uconrel[1]=pr[U1];
2458  uconrel[2]=pr[U2];
2459  uconrel[3]=pr[U3];
2460 
2461  // SLOOPA(j) dualfprintf(fail_file,"gamma_calc: uconrel[%d]=%21.15g\n",j,uconrel[j]); // CHANGINGMARK
2462 
2463 
2464  // get gamma
2465  MYFUN(gamma_calc_fromuconrel(uconrel, geom, gamma, qsq),"gamma_calc: gamma_calc_fromuconrel failed\n","phys.c",1);
2466 
2467  return(0);
2468 }
2469 
2470 
2473 int gamma_calc_fromuconrel(FTYPE *uconrel, struct of_geom *geom, FTYPE*gamma, FTYPE *qsq)
2474 {
2475  int qsq_calc(FTYPE *uconrel, struct of_geom *geom, FTYPE *qsq);
2476 
2477 
2478  // get q^2 = \tilde{u}^i \tilde{u}^j g_{ij}
2479  qsq_calc(uconrel,geom,qsq);
2480 
2481 
2482 #if(JONCHECKS && PRODUCTION==0)
2483  VARSTATIC int j,k;
2484  if(*qsq<0.0){
2485  if(*qsq>-NUMEPSILON*100){ // then assume not just machine precision
2486  *qsq=0.0;
2487  }
2488  else{
2489  if(failed!=-1){
2490  dualfprintf(fail_file,"gamma_calc failed: i=%d j=%d k=%d qsq=%21.15g\n",geom->i,geom->j,geom->k,*qsq);
2491  SLOOPA(j) dualfprintf(fail_file,"uconrel[%d]=%21.15g\n",j,uconrel[j]);
2492  DLOOP(j,k) dualfprintf(fail_file,"gcov[%d][%d]=%21.15g\n",j,k,geom->gcov[GIND(j,k)]);
2493  }
2494  if (fail(geom->i,geom->j,geom->k,geom->p,FAIL_UTCALC_DISCR) >= 1)
2495  return (1);
2496  }
2497  }
2498 #else
2499  // minimal check -- forces qsq=0 if qsq<0.0
2500  *qsq = (*qsq)*((*qsq)>=0.0);
2501 #endif
2502 
2503  *gamma = sqrt(1. + (*qsq)) ;
2504 
2505  // SLOOPA(j) dualfprintf(fail_file,"uconrel[%d]=%21.15g\n",j,uconrel[j]);
2506  // dualfprintf(fail_file,"qsq=%21.15g, gamma=%21.15g\n",*qsq,*gamma); // CHANGINGMARK
2507 
2508  return(0) ;
2509 }
2510 
2511 
2514 int qsq_calc(FTYPE *uconrel, struct of_geom *geom, FTYPE *qsq)
2515 {
2516  // VARSTATIC int j,k;
2517 
2518  *qsq =
2519  + geom->gcov[GIND(1,1)]*uconrel[1]*uconrel[1]
2520  + geom->gcov[GIND(2,2)]*uconrel[2]*uconrel[2]
2521  + geom->gcov[GIND(3,3)]*uconrel[3]*uconrel[3]
2522 #if(DOMIXTHETAPHI)
2523  + 2.*(geom->gcov[GIND(1,2)]*uconrel[1]*uconrel[2]
2524  + geom->gcov[GIND(1,3)]*uconrel[1]*uconrel[3]
2525  + geom->gcov[GIND(2,3)]*uconrel[2]*uconrel[3])
2526 #else
2527  + 2.*(geom->gcov[GIND(1,2)]*uconrel[1]*uconrel[2]
2528  + geom->gcov[GIND(1,3)]*uconrel[1]*uconrel[3])
2529 #endif
2530  ;
2531 
2532  // DLOOP(j,k) dualfprintf(fail_file,"gcov[%d][%d]=%21.15g uconrel[%d]=%21.15g uconrel[%d]=%21.15g\n",j,k,geom->gcov[GIND(j,k)],j,uconrel[j],k,uconrel[k]); // CHANGINGMARK
2533 
2534  return(0) ;
2535 }
2536 
2537 
2538 
2539 
2540 
2541 
2544 int ucon_calc_3vel(FTYPE *pr, struct of_geom *geom, FTYPE *ucon, FTYPE *others)
2545 {
2546  VARSTATIC FTYPE negdiscr;
2547  VARSTATIC FTYPE velterm;
2548  VARSTATIC FTYPE vcon[NDIM];
2549  // debug stuff
2550  VARSTATIC int j,k;
2551  VARSTATIC FTYPE V[NDIM],X[NDIM];
2552  //
2553  int get_3velterm(FTYPE *vcon, struct of_geom *geom, FTYPE *velterm);
2554 
2555 
2556 
2557  SLOOPA(j) vcon[j] = pr[U1+j-1];
2558 
2559  get_3velterm(vcon, geom, &velterm);
2560 
2561  negdiscr = geom->gcov[GIND(0,0)] + velterm ;
2562 
2563 
2564 #if(JONCHECKS && WHICHVEL==VEL3)
2565  uttdiscr=-negdiscr;
2566 #endif
2567 
2568  if (negdiscr > 0.) {
2569 #if(JONCHECKS)
2570  if(failed!=-1){
2571  if(whocalleducon==0){
2572  // then report on disc
2573  dualfprintf(fail_file,"negdisc=%21.15g, should be negative\n",negdiscr);
2574  for(k=U1;k<=U3;k++){
2575  dualfprintf(fail_file,"uconfailed on pr[%d]=%21.15g\n",k,pr[k]);
2576  }
2577  bl_coord_ijk_2(geom->i,geom->j,geom->k,geom->p,X, V);
2578  dualfprintf(fail_file,"i=%d j=%d k=%d pcurr=%d\nx1=%21.15g x2=%21.15g x3=%21.15g \nV1=%21.15g V2=%21.15g V3=%21.15g \ng=%21.15g\n",startpos[1]+geom->i,startpos[2]+geom->j,startpos[3]+geom->k,geom->p,X[1],X[2],X[3],V[1],V[2],V[3],geom->gdet);
2579  dualfprintf(fail_file,"\ngcon\n");
2580  dualfprintf(fail_file,"{");
2581  for(j=0;j<NDIM;j++){
2582  dualfprintf(fail_file,"{");
2583  for(k=0;k<NDIM;k++){
2584  dualfprintf(fail_file,"%21.15g",geom->gcon[GIND(j,k)]);
2585  if(k!=NDIM-1) dualfprintf(fail_file," , ");
2586  }
2587  dualfprintf(fail_file,"}");
2588  if(j!=NDIM-1) dualfprintf(fail_file," , ");
2589  }
2590  dualfprintf(fail_file,"}");
2591  dualfprintf(fail_file,"\ngcov\n");
2592  dualfprintf(fail_file,"{");
2593  for(j=0;j<NDIM;j++){
2594  dualfprintf(fail_file,"{");
2595  for(k=0;k<NDIM;k++){
2596  dualfprintf(fail_file,"%21.15g",geom->gcov[GIND(j,k)]);
2597  if(k!=NDIM-1) dualfprintf(fail_file," , ");
2598  }
2599  dualfprintf(fail_file,"}");
2600  if(j!=NDIM-1) dualfprintf(fail_file," , ");
2601  }
2602  dualfprintf(fail_file,"}");
2603  }
2604  }
2605 #endif
2606  if (fail(geom->i,geom->j,geom->k,geom->p,FAIL_UTCALC_DISCR) >= 1)
2607  return (1);
2608  }
2609 
2610  ucon[TT] = 1. / sqrt(-negdiscr);
2611  SLOOPA(j) ucon[j]=vcon[j]*ucon[TT];
2612 
2613  return (0);
2614 }
2615 
2616 
2618 int get_3velterm(FTYPE *vcon, struct of_geom *geom, FTYPE *velterm)
2619 {
2620  VARSTATIC int j;
2621 
2622 
2623  *velterm =
2624  + geom->gcov[GIND(1,1)] * vcon[1] * vcon[1]
2625  + geom->gcov[GIND(2,2)] * vcon[2] * vcon[2]
2626  + geom->gcov[GIND(3,3)] * vcon[3] * vcon[3]
2627  + 2. * (geom->gcov[GIND(0,1)]* vcon[1]
2628  + geom->gcov[GIND(0,2)] * vcon[2]
2629  + geom->gcov[GIND(0,3)] * vcon[3]
2630  + geom->gcov[GIND(1,2)] * vcon[1] * vcon[2]
2631  + geom->gcov[GIND(1,3)] * vcon[1] * vcon[3]
2632  + geom->gcov[GIND(2,3)] * vcon[2] * vcon[3]
2633  );
2634  return(0);
2635 }
2636 
2637 
2638 
2639 
2640 
2641 
2645 int limit_3vel_ffde(FTYPE *Bcon, struct of_geom *geom, FTYPE *vcon, FTYPE *pr)
2646 {
2647  int dualf_calc(FTYPE *Bcon, FTYPE *vcon, FTYPE (*dualffull)[NDIM]);
2648  void ffdestresstensor(FTYPE (*Mcon)[NDIM], struct of_geom *geom, FTYPE (*T)[NDIM]);
2649  FTYPE dualf[NDIM][NDIM], T[NDIM][NDIM];
2650  int Utoprim_ffde(FTYPE *U, struct of_geom *geom, FTYPE *pr);
2651  FTYPE U[NPR];
2652 
2653 #if(EOMTYPE!=EOMFFDE && EOMTYPE!=EOMFFDE2)
2654  dualfprintf(fail_file,"Only call limit_3vel_ffde() if doing EOMTYPE==EOMFFDE || EOMTYPE==EOMFFDE2\n");
2655  myexit(346983463);
2656 #endif
2657 
2658 
2660  //
2661  // get \dF^{\mu\nu}
2662  //
2664  dualf_calc(Bcon, vcon, dualf);
2665 
2667  //
2668  // get T^\mu_\nu
2669  //
2671  ffdestresstensor(dualf, geom, T);
2672 
2673 
2675  //
2676  // setup conserved quantities
2677  //
2679  U[RHO] = 0;
2680  U[UU] = T[0][0]; // T^t_t
2681  U[U1] = T[0][1]; // T^t_x
2682  U[U2] = T[0][2]; // T^t_y
2683  U[U3] = T[0][3]; // T^t_z
2684  U[B1] = Bcon[1];
2685  U[B2] = Bcon[2];
2686  U[B3] = Bcon[3];
2687 
2688 
2689 
2691  //
2692  // filter through inversion so v^i is limited to have Lorentz factor <=GAMMAMAX
2693  //
2695 
2696 
2697  // Utoprim_ffde(U, geom, pr);
2698  int showmessages=1;
2699  int allowlocalfailurefixandnoreport=1;
2700  struct of_newtonstats newtonstats; setnewtonstatsdefault(&newtonstats);
2701  // initialize counters
2702  newtonstats.nstroke=newtonstats.lntries=0;
2703  int finalstep=1; // doesn't matter for ffde
2704  int eomtype=EOMDEFAULT;
2705  FTYPE dissmeasure=-1.0; // assume trying energy ok
2706  int whichcap=CAPTYPEBASIC;
2707  int whichmethod=MODEDEFAULT;
2708  int modprim=0;
2709  int checkoninversiongas=CHECKONINVERSION;
2710  int checkoninversionrad=CHECKONINVERSIONRAD;
2711  MYFUN(Utoprimgen(showmessages,checkoninversiongas,checkoninversionrad,allowlocalfailurefixandnoreport, finalstep,&eomtype,whichcap,whichmethod,modprim,EVOLVEUTOPRIM,UNOTHING,U, NULL, geom, dissmeasure, pr, pr,&newtonstats),"step_ch.c:advance()", "Utoprimgen", 1);
2712  // nstroke+=newtonstats.nstroke; newtonstats.nstroke=newtonstats.lntries=0;
2713 
2714 
2715 
2716  return(0);
2717 
2718 }
2719 
2720 
2721 
2722 
2724 int ucon_calc_4vel_bothut(FTYPE *pr, struct of_geom *geom, FTYPE *ucon, FTYPE *ucon2, FTYPE *others)
2725 {
2726  VARSTATIC int i,j,k;
2727  VARSTATIC FTYPE AA,BB,CCM1 ;
2728  VARSTATIC FTYPE discr ;
2729  VARSTATIC FTYPE bsq,X[NDIM] ;
2730  VARSTATIC FTYPE sqrtdiscr;
2731  int get_4velterms(FTYPE *ucon, struct of_geom *geom, FTYPE *AA, FTYPE *BB, FTYPE *CCM1, FTYPE *discr);
2732 
2733 
2734  ucon[1] = pr[U1] ;
2735  ucon[2] = pr[U2] ;
2736  ucon[3] = pr[U3] ;
2737 
2738  ucon2[1] = pr[U1] ;
2739  ucon2[2] = pr[U2] ;
2740  ucon2[3] = pr[U3] ;
2741 
2742  get_4velterms(ucon, geom, &AA, &BB, &CCM1, &discr);
2743 
2744  if(discr < 0.) {
2745  /*
2746  dualfprintf(fail_file,"failure") ;
2747  ucon[TT] = (-BB - sqrt(-discr))/(2.*AA) ;
2748  ucon[TT] = -BB/(2.*AA) ;
2749  */
2750  dualfprintf(fail_file,"failure: spacelike four-velocity %21.15g\n",
2751  discr) ;
2752  dualfprintf(fail_file,"i=%d j=%d k=%d p=%d\n",startpos[1]+geom->i,startpos[2]+geom->j,startpos[3]+geom->k,geom->p) ;
2753  coord(geom->i,geom->j,geom->k,geom->p,X);
2754  dualfprintf(fail_file,"%21.15g %21.15g %21.15g\n",X[1],X[2],X[3]) ;
2755 
2756  for(k=0;k<NPR;k++) dualfprintf(fail_file,"%d %21.15g\n",k,pr[k]) ;
2757  // GODMARK -- why did we have failed=1?
2758  // failed=1;
2759  return(1);
2760  }
2761 
2762  sqrtdiscr=sqrt(discr);
2763 
2764  ucon[TT] = (-BB - sqrtdiscr)/(2.*AA) ; // standard solution always valid outside ergosphere
2765  ucon2[TT] = (-BB + sqrtdiscr)/(2.*AA) ; // can be a valid solution within ergosphere
2766 
2767  return(0) ;
2768 }
2769 
2770 
2772 int ucon_calc_4vel(FTYPE *pr, struct of_geom *geom, FTYPE *ucon, FTYPE *others)
2773 {
2774  VARSTATIC int i,j,k;
2775  VARSTATIC FTYPE AA,BB,CCM1 ;
2776  VARSTATIC FTYPE discr ;
2777  VARSTATIC FTYPE bsq,X[NDIM] ;
2778  int get_4velterms(FTYPE *ucon, struct of_geom *geom, FTYPE *AA, FTYPE *BB, FTYPE *CCM1, FTYPE *discr);
2779 
2780 
2781  ucon[1] = pr[U1] ;
2782  ucon[2] = pr[U2] ;
2783  ucon[3] = pr[U3] ;
2784 
2785  get_4velterms(ucon, geom, &AA, &BB, &CCM1, &discr);
2786 
2787  if(discr < 0.) {
2788  /*
2789  dualfprintf(fail_file,"failure\n") ;
2790  ucon[TT] = (-BB - sqrt(-discr))/(2.*AA) ;
2791  ucon[TT] = -BB/(2.*AA) ;
2792  */
2793  dualfprintf(fail_file,"failure: spacelike four-velocity %21.15g\n",
2794  discr) ;
2795  dualfprintf(fail_file,"i=%d j=%d k=%d p=%d\n",startpos[1]+geom->i,startpos[2]+geom->j,startpos[3]+geom->k,geom->p) ;
2796  coord(geom->i,geom->j,geom->k,geom->p,X);
2797  dualfprintf(fail_file,"%21.15g %21.15g %21.15g\n",X[1],X[2],X[3]) ;
2798 
2799  for(k=0;k<NPR;k++) dualfprintf(fail_file,"%d %21.15g\n",k,pr[k]) ;
2800  // GODMARK -- why did we have failed=1?
2801  // failed=1;
2802  return(1);
2803  }
2804 
2805  ucon[TT] = (-BB - sqrt(discr))/(2.*AA) ;
2806 
2807  return(0) ;
2808 }
2809 
2810 
2811 int get_4velterms(FTYPE *ucon, struct of_geom *geom, FTYPE *AA, FTYPE *BB, FTYPE *CCM1, FTYPE *discr)
2812 {
2813  VARSTATIC FTYPE CC;
2814 
2815  // g_{tt}
2816  *AA = geom->gcov[GIND(TT,TT)] ;
2817 
2818  // 2 u^i g_{it}
2819  *BB = 2.*(geom->gcov[GIND(TT,1)]*ucon[1] +
2820  geom->gcov[GIND(TT,2)]*ucon[2] +
2821  geom->gcov[GIND(TT,3)]*ucon[3]) ;
2822 
2823  // u^i u^j g_{ij}
2824  *CCM1 = geom->gcov[GIND(1,1)]*ucon[1]*ucon[1] +
2825  geom->gcov[GIND(2,2)]*ucon[2]*ucon[2] +
2826  geom->gcov[GIND(3,3)]*ucon[3]*ucon[3] +
2827  2.*(geom->gcov[GIND(1,2)]*ucon[1]*ucon[2] +
2828  geom->gcov[GIND(1,3)]*ucon[1]*ucon[3] +
2829  geom->gcov[GIND(2,3)]*ucon[2]*ucon[3]) ;
2830 
2831  // 1 + u^i u^j g_{ij}
2832  CC = *CCM1 + 1.0;
2833 
2834  // B^2 - 4AC
2835  *discr = (*BB)*(*BB) - 4.*(*AA)*CC ;
2836 
2837  return(0);
2838 }
2839 
2840 
2842 int ucon_calc_nonrel(FTYPE *pr, struct of_geom *geom, FTYPE *ucon, FTYPE *others)
2843 {
2844 
2845  // GODMARK: this isn't really right: neglects kinetic energy term. Need to really re-write T^\mu_\nu
2846 
2847  ucon[1] = pr[U1] ;
2848  ucon[2] = pr[U2] ;
2849  ucon[3] = pr[U3] ;
2850  ucon[TT] = 1.0;
2851 
2852  return(0) ;
2853 }
2854 
2855 
2857 {
2858 
2859  if(R <= rin)
2860  return(0.) ;
2861  else
2862  return(1. - sqrt(rin/R)) ;
2863 
2864 }
2865 
2866 
2867 
2868 
2869 
2873 FTYPE lc4(int updown, FTYPE detg, int mu,int nu,int kappa,int lambda)
2874 {
2875  int i;
2876  FTYPE lc4sign; // 1,-1,1,-1... for all 24 entires
2877  int l1[24]={1, 2, 3, 1, 2, 3, 4, 2, 1, 4, 2, 1, 1, 3, 4, 1, 3, 4, 4, 3, 2, 4, 3, 2};
2878  int l2[24]={2, 1, 1, 3, 3, 2, 2, 4, 4, 1, 1, 2, 3, 1, 1, 4, 4, 3, 3, 4, 4, 2, 2, 3};
2879  int l3[24]={3, 3, 2, 2, 1, 1, 1, 1, 2, 2, 4, 4, 4, 4, 3, 3, 1, 1, 2, 2, 3, 3, 4, 4};
2880  int l4[24]={4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1};
2881 
2882  for(i=0;i<24;i++){
2883  if((1+mu==l1[i])&&(1+nu==l2[i])&&(1+kappa==l3[i])&&(1+lambda==l4[i])){
2884  lc4sign=(i%2) ? -1 : 1;
2885  if(updown==1) return(-1.0/detg*lc4sign); // up
2886  else if(updown==0) return(detg*lc4sign); // down
2887  }
2888  }
2889  // if didn't get here, then 0
2890  return(0.0);
2891 }
2892 
2895 void faraday_calc(int which, FTYPE *b, FTYPE *u, struct of_geom *geom, FTYPE (*faraday)[NDIM])
2896 {
2897  int nu,mu,kappa,lambda;
2898 
2899  for(nu=0;nu<NDIM;nu++) for(mu=0;mu<NDIM;mu++){
2900  faraday[mu][nu]=0.0;
2901  for(kappa=0;kappa<NDIM;kappa++) for(lambda=0;lambda<NDIM;lambda++){
2902  faraday[mu][nu]+=lc4(which,geom->gdet,mu,nu,kappa,lambda)*u[kappa]*b[lambda];
2903  }
2904  }
2905 
2906 }
2907 
2908 
2909 
2910 
2915 {
2916  if(a>0.0) return 1.0;
2917  else if(a<0.0) return -1.0;
2918  else return 0.0;
2919 }
2920 
2921 
2924 {
2925 #if(SUPERLONGDOUBLE)
2926  return(sign(a));
2927  // no such function
2928 #else
2929  return(copysign(1.0,a));
2930 #endif
2931 }
2932 
2937 {
2938  if(a>0.0) return 1.0;
2939  else if(a<0.0) return -1.0;
2940  else return 1.0; // arbitrarily choose 1.0
2941 }
2942 
2943 
2944 
2945 #ifndef WIN32
2946 
2947 #ifndef max
2949 {
2950  if(a>b) return a;
2951  else return b;
2952  // if equal, then above is fine
2953 }
2954 #endif
2955 
2956 #ifndef min
2958 {
2959  if(a>b) return b;
2960  else return a;
2961  // if equal, then above is fine
2962 }
2963 #endif
2964 
2965 #endif
2966 
2969 int sol(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *vmax, FTYPE *vmin)
2970 {
2971  int i,j,k;
2972  FTYPE vu[NDIM],BB,CC,vsol1p,vsol1m;
2973  FTYPE ftemp1,ftemp2,ftemp3;
2974  FTYPE disc;
2975  int diro1,diro2;
2976 
2977  /*
2978  m%3+1 gives next 1->2,2->3,3->1
2979  3-(4-m)%3 gives previous 1->3,2->1,3->2
2980  */
2981  diro1=dir%3+1;
2982  diro2=3-(4-dir)%3;
2983 
2984  // 3-velocity in coordinate frame
2985  SLOOPA(j) vu[j]=q->ucon[j]/q->ucon[TT];
2986 
2987  ftemp1=0;
2988  ftemp2=0;
2989  ftemp3=0;
2990  SLOOPA(j){
2991  if(j!=dir){
2992  ftemp1+=vu[j]*geom->gcov[GIND(dir,j)];
2993  ftemp2+=vu[j]*geom->gcov[GIND(TT,j)];
2994  ftemp3+=vu[j]*vu[j]*geom->gcov[GIND(j,j)];
2995  }
2996  }
2997 
2998  BB=2.0*(ftemp1+geom->gcov[GIND(0,dir)])/geom->gcov[GIND(dir,dir)];
2999  CC=(geom->gcov[GIND(TT,TT)] + 2.0*ftemp2 + ftemp3 + 2.0*vu[diro1]*vu[diro2]*geom->gcov[GIND(diro1,diro2)])/geom->gcov[GIND(dir,dir)];
3000 
3001  disc=BB*BB-4.0*CC;
3002  if(disc>0){
3003  *vmax=0.5*(-BB+sqrt(disc));
3004  *vmin=0.5*(-BB-sqrt(disc));
3005  }
3006  else{
3007  dualfprintf(fail_file,"disc=%21.15g < 0\n",disc);
3008  return(1);
3009  }
3010 
3011  return(0);
3012 
3013 }
3014 
3015 
3017 int limitv3(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *v)
3018 {
3019  FTYPE vmax,vmin;
3020  int sol(FTYPE *pr, struct of_state *q, int dir, struct of_geom *geom, FTYPE *vmax, FTYPE *vmin);
3021  FTYPE ratv;
3022 
3023  // get speed of light 3-velocity
3024  MYFUN(sol(pr,q,dir,geom,&vmax,&vmin),"phys.c:limitv3()", "sol()", 1);
3025 
3026  // get ratio of given 3-velocity to speed of light 3-velocity for appropriate direction of coordinate-based velocity
3027  ratv=(*v>0) ? *v/vmax : *v/vmin;
3028 
3029  // limit 3-velocity to speed of light
3030  if(ratv>1.0){
3031  if(*v>0.0) *v=vmax;
3032  else *v=vmin;
3033  }
3034 
3035  return(0);
3036 }
3037 
3041 void projectionvec(int vcon,int vresultcon, struct of_state *q, struct of_geom *geom,FTYPE *v,FTYPE*vresult)
3042 {
3043  FTYPE proj[NDIM][NDIM];
3044  int j,k;
3045 
3046 
3047  if((vcon)&&(vresultcon)){ // vresult^\mu = P^\mu_\nu v^\nu
3048  DLOOP(j,k) proj[j][k]=delta(j,k) + q->ucon[j]*q->ucov[k];
3049  }
3050  if((!vcon)&&(!vresultcon)){ // vresult_\mu = P_\mu^\nu v_\nu
3051  DLOOP(j,k) proj[j][k]=delta(j,k) + q->ucov[j]*q->ucon[k];
3052  }
3053  else if((!vcon)&&(vresultcon)){ // vresult^\mu = P^{\mu\nu} v_\nu
3054  DLOOP(j,k) proj[j][k]=geom->gcon[GIND(j,k)] + q->ucon[j]*q->ucon[k];
3055  }
3056  else if((vcon)&&(!vresultcon)){ // vresult_\mu = P_{\mu\nu} v^\nu
3057  DLOOP(j,k) proj[j][k]=geom->gcov[GIND(j,k)] + q->ucov[j]*q->ucov[k];
3058  }
3059  DLOOPA(j) vresult[j]=0.0;
3060  DLOOP(j,k) vresult[j]+=proj[j][k]*v[k];
3061 
3062 
3063 }
3064 
3065 
3067 void compute_gconttplus1(struct of_geom *geom, FTYPE *gconttplus1)
3068 {
3069  int j,k;
3070  FTYPE gconttsq;
3071 
3072  // accurate for non-rel gravity since gconttsq is order v^4
3073  // could store gconttplus1 instead
3074  gconttsq = (geom->gcon[GIND(TT,TT)]*geom->gcon[GIND(TT,TT)]);
3075  *gconttplus1= (geom->gcovpert[TT]) * gconttsq + (1.0-gconttsq);
3076  SLOOPA(j) *gconttplus1 += 2.0*geom->gcov[GIND(TT,j)]*(geom->gcon[GIND(j,TT)]*geom->gcon[GIND(j,TT)]);
3077  SLOOP(j,k) *gconttplus1 += geom->gcov[GIND(j,k)]*geom->gcon[GIND(j,TT)]*geom->gcon[GIND(k,TT)];
3078 
3079 }
3080 
3083 int quasivsq_3vel(FTYPE *vcon, struct of_geom *geom, FTYPE *quasivsq)
3084 {
3085  int i,j,k;
3086  FTYPE gcovttplus1, gconttplus1;
3087  FTYPE velterm;
3088  int get_3velterm(FTYPE *vcon, struct of_geom *geom, FTYPE *velterm);
3089  void compute_gconttplus1(struct of_geom *geom, FTYPE *gconttplus1);
3090 
3091 
3092  // since (u^t)^2 = -1/ (g_{tt} + 2v^i g_{it} + v^2 )
3093  // where v^2 = v^i v^j g_{ij}
3094  //
3095  // then (u^t)^2 - 1 = [(1 + g_{tt}) + (2v^i g_{it} + v^2)]/[ - g_{tt} - (2v^i g_{it} + v^2) ]
3096 
3097  // later this can be initialized as it's own variable when wanting to do non-rel gravity
3098  // gcovttplus1 = geom->gcov[GIND(TT,TT)] + 1.0;
3099  gcovttplus1 = geom->gcovpert[TT];
3100 
3101  // gconttplus1= geom->gcon[GIND(TT,TT)] + 1.0;
3102  compute_gconttplus1(geom,&gconttplus1);
3103 
3104 
3105  get_3velterm(vcon, geom, &velterm);
3106 
3107  // this has a good machine representable value in the limit of non-rel velocities
3108  // *utsqm1 = (gcovttplus1 + velterm) / (-geom->gcov[GIND(TT,TT)] - velterm);
3109 
3110  // decided to use (u^t)^2 - 1 + (g^{tt} + 1)
3111  *quasivsq = (gcovttplus1 + velterm) / (-geom->gcov[GIND(TT,TT)] - velterm) + gconttplus1 ;
3112 
3113  return(0);
3114 
3115 
3116 }
3117 
3118 
3119 int quasivsq_4vel(FTYPE *pr, struct of_geom *geom, FTYPE *quasivsq)
3120 {
3121  FTYPE AA,BB,CCM1,CCPLUSAA ;
3122  FTYPE discr ;
3123  FTYPE bsq,X[NDIM] ;
3124  int i=0,j=0,k=0 ;
3125  FTYPE gcovttplus1,gconttplus1;
3126  int get_4velterms(FTYPE *ucon, struct of_geom *geom, FTYPE *AA, FTYPE *BB, FTYPE *CCM1, FTYPE *discr);
3127  FTYPE ucon[NDIM];
3128  void compute_gconttplus1(struct of_geom *geom, FTYPE *gconttplus1);
3129 
3130 
3131  ucon[1] = pr[U1] ;
3132  ucon[2] = pr[U2] ;
3133  ucon[3] = pr[U3] ;
3134 
3135  // coefficients for quadratic solution
3136  get_4velterms(ucon, geom, &AA, &BB, &CCM1, &discr);
3137 
3138  if(discr<0){
3139  dualfprintf(fail_file,"Problem with utsqm1_4vel\n");
3140  return(1);
3141  }
3142 
3143  // 1.0 + g_{tt}
3144  gcovttplus1 = geom->gcovpert[TT];
3145 
3146  // gconttplus1= geom->gcon[GIND(TT,TT)] + 1.0;
3147  compute_gconttplus1(geom,&gconttplus1);
3148 
3149  // v^2 in non-rel case
3150  CCPLUSAA = gcovttplus1 + CCM1;
3151 
3152  // first term is genuinely relativistic, so no correction needed for non-rel case
3153  // second term is combination of |discr| and -4A^2
3154  // in the non-rel limit this reduces (for BB=0 and AA=-1) to CCPLUSAA, which is v^2
3155  // *utsqm1 = ( BB*(BB + sqrt(discr)) + fabs(BB*BB - 4.0*AA*CCPLUSAA) ) /(4.0*AA*AA) ;
3156 
3157  // decided to use (u^t)^2 - 1 + (g^{tt} + 1)
3158  *quasivsq = ( BB*(BB + sqrt(discr)) + fabs(BB*BB - 4.0*AA*CCPLUSAA) ) /(4.0*AA*AA) + gconttplus1;
3159 
3160  return(0) ;
3161 
3162 
3163 }
3164 
3165 
3168 int quasivsq_rel4vel(FTYPE *uconrel, struct of_geom *geom, FTYPE *quasivsq)
3169 {
3170  FTYPE alphasq;
3171  FTYPE qsq;
3172  FTYPE timeterm;
3173  int j ;
3174  int qsq_calc(FTYPE *uconrel, struct of_geom *geom, FTYPE *qsq);
3175 
3176  // alpha = 1./sqrt(-geom->gcon[GIND(TT,TT)]) ;
3177 
3178  alphasq=1./(-geom->gcon[GIND(TT,TT)]); // positive definite and 1 in non-rel case
3179 
3180  //timeterm = -(geom->gcon[GIND(TT,TT)] + 1.0 ); // ~0 in non-rel case, and equal to 1+g_{tt} in non-rel case, which is always positive
3181 
3182  qsq_calc(uconrel,geom,&qsq);
3183 
3184  // *utsqm1 = qsq/alphasq + timeterm ;
3185 
3186  // decided to use (u^t)^2 - 1 + (g^{tt} + 1) = utsqm1 - timeterm
3187  // already accurate to order v^2 when non-rel velocity/gravity used
3188  *quasivsq = qsq/alphasq;
3189 
3190  return(0) ;
3191 }
3192 
3193 
3195 int quasivsq_compute(FTYPE *pr, struct of_geom *geom, FTYPE *quasivsq)
3196 {
3197  int quasivsq_3vel(FTYPE *vcon, struct of_geom *geom, FTYPE *quasivsq);
3198  int quasivsq_4vel(FTYPE *ucon, struct of_geom *geom, FTYPE *quasivsq);
3199  int quasivsq_rel4vel(FTYPE *uconrel, struct of_geom *geom, FTYPE *quasivsq);
3200  FTYPE ucon[NDIM],vcon[NDIM],uconrel[NDIM];
3201 
3202 
3203 #if(WHICHVEL==VEL4)
3204 
3205  ucon[1]=pr[U1];
3206  ucon[2]=pr[U2];
3207  ucon[3]=pr[U3];
3208  return(quasivsq_4vel(ucon, geom, quasivsq));
3209 
3210 #elif(WHICHVEL==VEL3)
3211 
3212  vcon[1]=pr[U1];
3213  vcon[2]=pr[U2];
3214  vcon[3]=pr[U3];
3215  return(quasivsq_3vel(vcon, geom, quasivsq));
3216 
3217 #elif(WHICHVEL==VELREL4)
3218 
3219  uconrel[1]=pr[U1];
3220  uconrel[2]=pr[U2];
3221  uconrel[3]=pr[U3];
3222  return(quasivsq_rel4vel(uconrel, geom, quasivsq));
3223 
3224 #endif
3225 
3226  // return(0);
3227 
3228 }
3229 
3230 int limit_quasivsq(FTYPE quasivsqnew, struct of_geom *geom, FTYPE *pr)
3231 {
3232  int limit_quasivsq_3vel(FTYPE quasivsqold, FTYPE quasivsqnew, struct of_geom *geom, FTYPE *vcon);
3233  int limit_quasivsq_4vel(FTYPE quasivsqold, FTYPE quasivsqnew, struct of_geom *geom, FTYPE *ucon);
3234  int limit_quasivsq_rel4vel(FTYPE quasivsqold, FTYPE quasivsqnew, struct of_geom *geom, FTYPE *uconrel);
3235  FTYPE ucon[NDIM],vcon[NDIM],uconrel[NDIM];
3236  int quasivsq_compute(FTYPE *pr, struct of_geom *geom, FTYPE *quasivsq);
3237  FTYPE quasivsqold;
3238 
3239 
3240  // get pr's quasivsq
3241  if(quasivsq_compute(pr, geom, &quasivsqold)>=1){
3242  dualfprintf(fail_file,"Problem with limit_quasivsq using quasivsq_compute\n");
3243  myexit(3);
3244  }
3245 
3246  // dualfprintf(fail_file,"IN: v^x = %21.15g v^y = %21.15g v^z = %21.15g :: old = %21.15g new=%21.15g\n",pr[U1],pr[U2],pr[U3],quasivsqold,quasivsqnew);
3247 
3248  // now rescale the velocities to agree with quasivsqnew
3249 #if(WHICHVEL==VEL4)
3250 
3251  ucon[1]=pr[U1];
3252  ucon[2]=pr[U2];
3253  ucon[3]=pr[U3];
3254  limit_quasivsq_4vel(quasivsqold,quasivsqnew, geom, ucon);
3255  pr[U1]=ucon[1];
3256  pr[U2]=ucon[2];
3257  pr[U3]=ucon[3];
3258 
3259 #elif(WHICHVEL==VEL3)
3260 
3261  vcon[1]=pr[U1];
3262  vcon[2]=pr[U2];
3263  vcon[3]=pr[U3];
3264  limit_quasivsq_3vel(quasivsqold,quasivsqnew, geom, vcon);
3265  pr[U1]=vcon[1];
3266  pr[U2]=vcon[2];
3267  pr[U3]=vcon[3];
3268 
3269 #elif(WHICHVEL==VELREL4)
3270 
3271  uconrel[1]=pr[U1];
3272  uconrel[2]=pr[U2];
3273  uconrel[3]=pr[U3];
3274  limit_quasivsq_rel4vel(quasivsqold,quasivsqnew, geom, uconrel);
3275  pr[U1]=uconrel[1];
3276  pr[U2]=uconrel[2];
3277  pr[U3]=uconrel[3];
3278 
3279 #endif
3280 
3281  // dualfprintf(fail_file,"OUT: v^x = %21.15g v^y = %21.15g v^z = %21.15g :: old = %21.15g new=%21.15g\n",pr[U1],pr[U2],pr[U3],quasivsqold,quasivsqnew);
3282 
3283  return(0);
3284 
3285 }
3286 
3287 int limit_quasivsq_3vel(FTYPE quasivsqold,FTYPE quasivsqnew,struct of_geom *geom, FTYPE *vcon)
3288 {
3289  FTYPE pref;
3290 
3291  // quasivsq \propto q^2 \propto \tilde{u}^2, so trivial to rescale
3292  pref = sqrt(quasivsqnew/(quasivsqold+SMALL));
3293 
3294  // only true in non-rel case
3295  vcon[1]*=pref;
3296  vcon[2]*=pref;
3297  vcon[3]*=pref;
3298 
3299  return(0);
3300 }
3301 
3302 int limit_quasivsq_4vel(FTYPE quasivsqold,FTYPE quasivsqnew,struct of_geom *geom, FTYPE *ucon)
3303 {
3304  FTYPE pref;
3305 
3306  // quasivsq \propto q^2 \propto \tilde{u}^2, so trivial to rescale
3307  pref = sqrt(quasivsqnew/(quasivsqold+SMALL));
3308 
3309  // only true in non-rel case
3310  ucon[1]*=pref;
3311  ucon[2]*=pref;
3312  ucon[3]*=pref;
3313 
3314  return(0);
3315 }
3316 
3317 int limit_quasivsq_rel4vel(FTYPE quasivsqold,FTYPE quasivsqnew,struct of_geom *geom, FTYPE *uconrel)
3318 {
3319  FTYPE pref;
3320 
3321  // quasivsq \propto q^2 \propto \tilde{u}^2, so trivial to rescale
3322  pref = sqrt(quasivsqnew/(quasivsqold+SMALL));
3323 
3324  // relativistically correct
3325  uconrel[1]*=pref;
3326  uconrel[2]*=pref;
3327  uconrel[3]*=pref;
3328 
3329  return(0);
3330 }
3331 
3332 
3334 int OBtopr_general(FTYPE omegaf,FTYPE *Bccon,struct of_geom *geom, FTYPE *pr)
3335 {
3336  int j;
3337  FTYPE Bccov[NDIM];
3338  FTYPE Bsq;
3339  FTYPE ftemp,ftemp2;
3340  FTYPE vcon[NDIM];
3341 
3342 
3343  lower_vec(Bccon,geom,Bccov);
3344 
3345  Bsq=0.0+SMALL;
3346  SLOOPA(j) Bsq+=Bccon[j]*Bccov[j];
3347 
3348  ftemp=(Bccov[TT]+omegaf*Bccov[PH])/Bsq;
3349  // ftemp2 is set so that no round off error in limit where toroidal field dominates
3350  // Does this cause problem for frame-dragged fields?
3351  //ftemp2=omegaf*(1.0 - Bccov[PH]*Bccon[3]/Bsq);
3352  // below more accurate than above?
3353  ftemp2=omegaf*(Bccov[RR]*Bccon[RR]+Bccov[TH]*Bccon[TH])/Bsq;
3354 
3355  vcon[1] = -Bccon[1]*ftemp;
3356  vcon[2] = -Bccon[2]*ftemp;
3357  // vcon[3] = omegaf - Bccon[3]*ftemp;
3358  // designed so to avoid catastrophic cancellation like above has problems with
3359  vcon[3] = ftemp2 - (Bccon[3]*Bccov[TT]/Bsq);
3360 
3361 
3362  MYFUN(vcon2pr(WHICHVEL, vcon, geom, pr),"phys.c:OBtopr_general()", "vcon2pr() dir=0", 1);
3363 
3364  // if(t>1.9 && t<2.1){
3365  // dualfprintf(fail_file,"ftemp=%21.15g Bsq=%21.15g ftemp2=%21.15g :: v1=%21.15g v2=%21.15g v3=%21.15g pru1=%21.15g pru2=%21.15g pru3=%21.15g\n",ftemp,Bsq,ftemp2,vcon[1],vcon[2],vcon[3],pr[U1],pr[U2],pr[U3]);
3366  // }
3367 
3368  return(0);
3369 
3370 }
3371 
3372 
3373 
3375 int OBtopr_general2(FTYPE omegaf, FTYPE v0, FTYPE *Bccon,struct of_geom *geom, FTYPE *pr)
3376 {
3377  int j;
3378  FTYPE Bccov[NDIM];
3379  FTYPE Bsq;
3380  FTYPE ftemp,ftemp2;
3381  FTYPE vcon[NDIM];
3382  FTYPE v0oB;
3383 
3384  lower_vec(Bccon,geom,Bccov);
3385 
3386  Bsq=0.0+SMALL;
3387  SLOOPA(j) Bsq+=Bccon[j]*Bccov[j];
3388 
3389  v0oB=v0/sqrt(Bsq);
3390 
3391  ftemp=(Bccov[TT]+omegaf*Bccov[PH])/Bsq;
3392  // ftemp2 is set so that no round off error in limit where toroidal field dominates
3393  // Does this cause problem for frame-dragged fields?
3394  //ftemp2=omegaf*(1.0 - Bccov[PH]*Bccon[3]/Bsq);
3395  // below more accurate than above?
3396  ftemp2=omegaf*(Bccov[RR]*Bccon[RR]+Bccov[TH]*Bccon[TH])/Bsq;
3397 
3398  vcon[1] = (v0oB-ftemp)*Bccon[1];
3399  vcon[2] = (v0oB-ftemp)*Bccon[2];
3400  // vcon[3] = omegaf - Bccon[3]*ftemp;
3401  // designed so to avoid catastrophic cancellation like above has problems with
3402  vcon[3] = ftemp2 + Bccon[3]*(v0oB-Bccov[TT]/Bsq);
3403 
3404 
3405  MYFUN(vcon2pr(WHICHVEL, vcon, geom, pr),"phys.c:OBtopr_general()", "vcon2pr() dir=0", 1);
3406 
3407  // if(t>1.9 && t<2.1){
3408  // dualfprintf(fail_file,"ftemp=%21.15g Bsq=%21.15g ftemp2=%21.15g :: v1=%21.15g v2=%21.15g v3=%21.15g pru1=%21.15g pru2=%21.15g pru3=%21.15g\n",ftemp,Bsq,ftemp2,vcon[1],vcon[2],vcon[3],pr[U1],pr[U2],pr[U3]);
3409  // }
3410 
3411  return(0);
3412 
3413 }
3414 
3416 int OBtopr_general3(FTYPE omegaf, FTYPE v0, FTYPE *Bccon,struct of_geom *geom, FTYPE *pr)
3417 {
3418  int j;
3419  FTYPE Bccov[NDIM];
3420  FTYPE Bsq;
3421  FTYPE absB;
3422  FTYPE v0other;
3423  FTYPE ftemp,ftemp2;
3424  FTYPE vcon[NDIM];
3425  FTYPE v0oB;
3426 
3427 
3428  //ensure outflow
3429  if (Bccon[1]<0) {
3430  v0 *= -1.;
3431  }
3432 
3433 
3434  lower_vec(Bccon,geom,Bccov);
3435 
3436  Bsq=0.0+SMALL;
3437  SLOOPA(j) Bsq+=Bccon[j]*Bccov[j];
3438 
3439  absB=sqrt(Bsq);
3440 
3441  vcon[1] = v0*Bccon[1]/absB;
3442  vcon[2] = v0*Bccon[2]/absB;
3443  vcon[3] = omegaf+v0*Bccon[3]/absB;
3444 
3445  MYFUN(vcon2pr(WHICHVEL, vcon, geom, pr),"phys.c:OBtopr_general()", "vcon2pr() dir=0", 1);
3446 
3447  return(0);
3448 
3449 }
3450 
3452 int OBtopr_general3p(FTYPE omegaf, FTYPE v0, FTYPE *Bccon,struct of_geom *geom, FTYPE *pr)
3453 {
3454  int j;
3455  FTYPE Bccov[NDIM];
3456  FTYPE Bsq_poloidal;
3457  FTYPE absB_poloidal;
3458  FTYPE v0other;
3459  FTYPE ftemp,ftemp2;
3460  FTYPE vcon[NDIM];
3461  FTYPE v0oB;
3462 
3463  lower_vec(Bccon,geom,Bccov);
3464 
3465  Bsq_poloidal=0.0+SMALL;
3466  SLOOPA(j) if( j <= 2 ) Bsq_poloidal+=Bccon[j]*Bccov[j]; //only poloidal components
3467 
3468  absB_poloidal=sqrt(Bsq_poloidal);
3469 
3470  vcon[1] = v0*Bccon[1]/absB_poloidal;
3471  vcon[2] = v0*Bccon[2]/absB_poloidal;
3472  vcon[3] = omegaf+v0*Bccon[3]/absB_poloidal;
3473 
3474  MYFUN(vcon2pr(WHICHVEL, vcon, geom, pr),"phys.c:OBtopr_general3p()", "vcon2pr() dir=0", 1);
3475 
3476  return(0);
3477 
3478 }
3479 
3480 
3481 
3482 
3484 int OBtopr_general3n(FTYPE omegaf, FTYPE v0, FTYPE *Bccon, FTYPE *normalvec,struct of_geom *geom, FTYPE *pr)
3485 {
3486  int j;
3487  FTYPE Bccov[NDIM];
3488  FTYPE Bsq_normal;
3489  FTYPE absB_normal;
3490  FTYPE v0other;
3491  FTYPE ftemp,ftemp2;
3492  FTYPE vcon[NDIM];
3493  FTYPE v0oB;
3494 
3495  FTYPE normalveccov[NDIM];
3496 
3497 
3498  lower_vec(Bccon,geom,Bccov);
3499  lower_vec(normalvec,geom,normalveccov);
3500 
3501  Bsq_normal=0.0;
3502  SLOOPA(j) Bsq_normal+=Bccon[j]*normalveccov[j];
3503 
3504  absB_normal=sqrt(Bsq_normal);
3505 
3506  vcon[1] = v0*Bccon[1]/absB_normal;
3507  vcon[2] = v0*Bccon[2]/absB_normal;
3508  vcon[3] = omegaf+v0*Bccon[3]/absB_normal;
3509 
3510  MYFUN(vcon2pr(WHICHVEL, vcon, geom, pr),"phys.c:OBtopr_general3p()", "vcon2pr() dir=0", 1);
3511 
3512  return(0);
3513 
3514 }
3515 
3516 
3517 void ffdestresstensor(FTYPE (*Mcon)[NDIM], struct of_geom *geom, FTYPE (*T)[NDIM])
3518 {
3519  int i,j,k ;
3520  void lower_A(FTYPE (*Acon)[NDIM], struct of_geom *geom, FTYPE (*Acov)[NDIM]);
3521 
3522 
3523  FTYPE Mcov[NDIM][NDIM] ; // covariant Maxwell
3524  FTYPE Msq ;
3525 
3526  // get covariant Maxwell from contravariant
3527  lower_A(Mcon, geom, Mcov) ;
3528 
3529  // out with the old
3530  DLOOP(j,k) T[j][k] = 0. ;
3531 
3532  /* in with the new:
3533  *
3534  * a, b, c, d run 0 to 4:
3535  *
3536  * T^a_b = M^ac * M_bc - 1/4 KroneckerDelta[a,b] (M_cd M^cd)
3537  *
3538  */
3539 
3540  Msq = 0. ;
3541  DLOOP(j,k) Msq += Mcov[j][k]*Mcon[j][k] ;
3542 
3543  DLOOP(j,k) {
3544  for(i = 0; i < NDIM; i++) {
3545  T[j][k] += Mcon[j][i]*Mcov[k][i] ;
3546  }
3547  }
3548  DLOOPA(j) T[j][j] -= 0.25 * Msq ;
3549 }
3550 
3551 
3554 void ffdestresstensor_dir(int dir, FTYPE (*Mcon)[NDIM], struct of_geom *geom, FTYPE *TEMdir)
3555 {
3556  int i,j,k ;
3557  void lower_A(FTYPE (*Acon)[NDIM], struct of_geom *geom, FTYPE (*Acov)[NDIM]);
3558 
3559 
3560  FTYPE Mcov[NDIM][NDIM] ; // covariant Maxwell
3561  FTYPE Msq ;
3562 
3563  // get covariant Maxwell from contravariant
3564  lower_A(Mcon, geom, Mcov) ;
3565 
3566  // out with the old
3567  DLOOPA(k) TEMdir[k] = 0. ;
3568 
3569  /* in with the new:
3570  *
3571  * a, b, c, d run 0 to 4:
3572  *
3573  * T^a_b = M^ac * M_bc - 1/4 KroneckerDelta[a,b] (M_cd M^cd)
3574  *
3575  */
3576 
3577  Msq = 0. ;
3578  DLOOP(j,k) Msq += Mcov[j][k]*Mcon[j][k] ;
3579 
3580  DLOOPA(k) {
3581  for(i = 0; i < NDIM; i++) {
3582  TEMdir[k] += Mcon[dir][i]*Mcov[k][i] ;
3583  }
3584  }
3585  TEMdir[dir] -= 0.25 * Msq ;
3586 }
3587 
3588 
3589 void raise_A(FTYPE (*Acov)[NDIM], struct of_geom *geom, FTYPE (*Acon)[NDIM])
3590 {
3591  int j,k ;
3592  FTYPE localgcon[SYMMATRIXNDIM];
3593 
3594  // out with the old
3595  DLOOP(j,k){
3596  Acon[j][k] = 0. ;
3597  // store since use all terms many times -- compiler doesn't do this for some reason
3598  localgcon[GIND(j,k)]=geom->gcon[GIND(j,k)];
3599  }
3600 
3601  // in with the new
3602  DLOOP(j,k) {
3603  Acon[0][1] += (localgcon[GIND(0,j)])*(localgcon[GIND(1,k)])*Acov[j][k] ;
3604  Acon[0][2] += (localgcon[GIND(0,j)])*(localgcon[GIND(2,k)])*Acov[j][k] ;
3605  Acon[0][3] += (localgcon[GIND(0,j)])*(localgcon[GIND(3,k)])*Acov[j][k] ;
3606  Acon[1][2] += (localgcon[GIND(1,j)])*(localgcon[GIND(2,k)])*Acov[j][k] ;
3607  Acon[2][3] += (localgcon[GIND(2,j)])*(localgcon[GIND(3,k)])*Acov[j][k] ;
3608  Acon[3][1] += (localgcon[GIND(3,j)])*(localgcon[GIND(1,k)])*Acov[j][k] ;
3609  }
3610 
3611  /*
3612  * diagonal is already set to zero,
3613  * just copy the rest
3614  */
3615 
3616  Acon[1][0] = - Acon[0][1] ;
3617  Acon[2][0] = - Acon[0][2] ;
3618  Acon[3][0] = - Acon[0][3] ;
3619  Acon[2][1] = - Acon[1][2] ;
3620  Acon[3][2] = - Acon[2][3] ;
3621  Acon[1][3] = - Acon[3][1] ;
3622 }
3623 
3624 void lower_A(FTYPE (*Acon)[NDIM], struct of_geom *geom, FTYPE (*Acov)[NDIM])
3625 {
3626  int j,k ;
3627  FTYPE localgcov[SYMMATRIXNDIM];
3628 
3629  // out with the old
3630  DLOOP(j,k){
3631  Acov[j][k] = 0. ;
3632  // store since use all terms many times -- compiler doesn't do this for some reason and lower_A() appears to be very costly
3633  localgcov[GIND(j,k)]=geom->gcov[GIND(j,k)];
3634  }
3635 
3636  // in with the new
3637  DLOOP(j,k) {
3638  Acov[0][1] += (localgcov[GIND(0,j)])*(localgcov[GIND(1,k)])*Acon[j][k] ;
3639  Acov[0][2] += (localgcov[GIND(0,j)])*(localgcov[GIND(2,k)])*Acon[j][k] ;
3640  Acov[0][3] += (localgcov[GIND(0,j)])*(localgcov[GIND(3,k)])*Acon[j][k] ;
3641  Acov[1][2] += (localgcov[GIND(1,j)])*(localgcov[GIND(2,k)])*Acon[j][k] ;
3642  Acov[2][3] += (localgcov[GIND(2,j)])*(localgcov[GIND(3,k)])*Acon[j][k] ;
3643  Acov[3][1] += (localgcov[GIND(3,j)])*(localgcov[GIND(1,k)])*Acon[j][k] ;
3644  }
3645 
3646  /*
3647  * diagonal is already set to zero,
3648  * just copy the rest
3649  */
3650 
3651  Acov[1][0] = - Acov[0][1] ;
3652  Acov[2][0] = - Acov[0][2] ;
3653  Acov[3][0] = - Acov[0][3] ;
3654  Acov[2][1] = - Acov[1][2] ;
3655  Acov[3][2] = - Acov[2][3] ;
3656  Acov[1][3] = - Acov[3][1] ;
3657 }
3658 
3659 
3660 
3661 
3668 void MtoF(int which, FTYPE (*invar)[NDIM],struct of_geom *geom, FTYPE (*outvar)[NDIM])
3669 {
3670  int nu,mu,kappa,lambda;
3671  FTYPE prefactor;
3672  int whichlc;
3673 
3674  if((which==0)||(which==1)){
3675  prefactor=-0.5;
3676  if(which==0) whichlc=0;
3677  if(which==1) whichlc=1;
3678  }
3679  if((which==2)||(which==3)){
3680  prefactor=0.5;
3681  if(which==2) whichlc=0;
3682  if(which==3) whichlc=1;
3683  }
3684 
3685  for(nu=0;nu<NDIM;nu++) for(mu=0;mu<NDIM;mu++){
3686  outvar[mu][nu]=0.0;
3687  for(kappa=0;kappa<NDIM;kappa++) for(lambda=0;lambda<NDIM;lambda++){
3688  outvar[mu][nu]+=prefactor*lc4(whichlc,geom->gdet,mu,nu,kappa,lambda)*invar[kappa][lambda];
3689  }
3690  }
3691 
3692 
3693 }
3694 
3695 
3697 int dualf_calc(FTYPE *Bcon, FTYPE *vcon, FTYPE (*dualffull)[NDIM])
3698 {
3699  int j,k;
3700 
3701  SLOOPA(j){
3702  // \dF^{it} = B^i
3703  dualffull[j][0] = Bcon[j];
3704  dualffull[0][j] = -Bcon[j];
3705  }
3706 
3707  DLOOPA(j) dualffull[j][j] = 0;
3708 
3709  // \dF^{ij} = B^i v^j - B^j v^i
3710  SLOOP(j,k) dualffull[j][k] = Bcon[j] * vcon[k] - Bcon[k] * vcon[j] ;
3711 
3712  return(0);
3713 
3714 }
3715 
3716 
3718 int set_zamo_velocity(int whichvel, struct of_geom *ptrgeom, FTYPE *pr)
3719 {
3720  int jj;
3721 
3722  // bl-normal observer (4-vel components)
3723 
3724  FTYPE etacov[NDIM],etacon[NDIM];
3725  etacov[TT]=-ptrgeom->alphalapse;
3726  etacov[RR]=0;
3727  etacov[TH]=0;
3728  etacov[PH]=0;
3729 
3730  raise_vec(etacov,ptrgeom,etacon);
3731 
3732  // normal observer velocity in atmosphere
3733  if(whichvel==VEL4){
3734  SLOOPA(jj) pr[U1+jj-1] = etacon[jj];
3735  }
3736  else if(whichvel==VEL3){
3737  SLOOPA(jj) pr[U1+jj-1] = etacon[jj]/etacon[TT];
3738  }
3739  else if(whichvel==VELREL4){
3740  SLOOPA(jj) pr[U1+jj-1] = 0.0;
3741  }
3742 
3743  return(0);
3744 
3745 }
3746 
3747 
3748 int set_zamo_ucovuconplus1ud0(struct of_geom *ptrgeom, FTYPE *ucov, FTYPE *ucon, FTYPE *plus1ud0)
3749 {
3750  FTYPE ialpha;
3751  FTYPE alpha;
3752  int j;
3753  FTYPE gconpert;
3754 
3755  // set alpha -- fabs just for roundoff error
3756  // ialpha=sqrt(fabs(-ptrgeom->gcon[GIND(TT,TT)]));
3757  alpha = ptrgeom->alphalapse;
3758  ialpha = 1.0/alpha;
3759 
3760  ucov[TT]=-alpha;
3761  SLOOPA(j) ucov[j]=0.0;
3762 
3763  raise_vec(ucov,ptrgeom,ucon);
3764 
3765  // 1+u_t
3766  // gconpert = ptrgeom->gconpert[TT]; // should be GODMARK
3767  gconpert = 0.0; // for now since this function now used GODMARK
3768 
3769  *plus1ud0 = fabs(gconpert)*alpha/(ialpha+1.0);
3770 
3771  return(0);
3772 
3773 }
3774 
3775 int set_zamo_ucon(struct of_geom *ptrgeom, FTYPE *ucon)
3776 {
3777  FTYPE ucov[NDIM];
3778  FTYPE plus1ud0;
3779 
3780  set_zamo_ucovuconplus1ud0(ptrgeom, ucov,ucon,&plus1ud0);
3781 
3782  return(0);
3783 
3784 }
3785 
3786 
3787 
3788 
3789 
3790 
3793 int entropy_calc(struct of_geom *ptrgeom, FTYPE *pr, FTYPE *entropy)
3794 {
3795 
3796  *entropy = compute_entropy_simple(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pr[RHO],pr[UU]);
3797 
3798  return(0);
3799 }
3800 
3803 int entropy_calc_forcheckinversion(struct of_geom *ptrgeom, FTYPE *pr, FTYPE *entropy)
3804 {
3805 
3806  *entropy = compute_entropy_simple_forcheckinversion(ptrgeom->i,ptrgeom->j,ptrgeom->k,ptrgeom->p,pr[RHO],pr[UU]);
3807 
3808  return(0);
3809 }
3810 
3811 
3812 
3814 FTYPE pressure_rho0_u_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3815 {
3816 
3817  return(pressure_rho0_u(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,u));
3818 
3819 }
3820 
3823 FTYPE pressure_rho0_u_simple_forcheckinversion(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3824 {
3825 
3826  if(WHICHEOS==KAZFULL && loc==CENT){
3827  // then avoid inconsistency by using stored pressure that was perhaps p(rho0,chi) instead of p(rho0,u)
3828  return(GLOBALMACP0A1(EOSextraglobal,i,j,k,PGASGLOBAL));
3829  }
3830  else{
3831  // then didn't store anything
3832  return(pressure_rho0_u(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,u));
3833  }
3834 
3835 }
3836 
3838 FTYPE u_rho0_p_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE p)
3839 {
3840 
3841  return(u_rho0_p(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,p));
3842 
3843 }
3844 
3846 FTYPE u_rho0_T_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE T)
3847 {
3848 
3849  return(u_rho0_T(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,T));
3850 
3851 }
3852 
3854 FTYPE cs2_compute_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3855 {
3856 
3857  return(cs2_compute(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,u));
3858 
3859 }
3860 
3863 FTYPE compute_entropy_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3864 {
3865  FTYPE entropy;
3866 
3867 
3868  // unlike inversion, require non-NaN entropy, so force rho,u to be positive
3869  if(rho<SMALL) rho=SMALL;
3870 
3871 #if(WHICHEOS!=KAZFULL)
3872  // for Kaz EOS, u<0 is ok
3873  if(u<SMALL) u=SMALL;
3874 #endif
3875 
3876  entropy=compute_entropy(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,u);
3877 
3878  if(!isfinite(entropy)) entropy=-BIG*MAX(rho,SMALL); // very negative corresponding to very little entropy.
3879 
3880  return(entropy);
3881 
3882 }
3883 
3886 FTYPE compute_entropy_simple_forcheckinversion(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3887 {
3888 
3889  if(WHICHEOS==KAZFULL && loc==CENT){
3890  // then avoid inconsistency by using stored pressure
3891  FTYPE chi = u + GLOBALMACP0A1(EOSextraglobal,i,j,k,PGASGLOBAL);
3892  return(rho*compute_specificentropy_wmrho0(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,chi));
3893  }
3894  else{
3895  // unlike inversion, require non-NaN entropy, so force rho,u to be positive
3896  if(rho<SMALL) rho=SMALL;
3897 #if(WHICHEOS!=KAZFULL)
3898  // for Kaz EOS, u<0 is ok
3899  if(u<SMALL) u=SMALL;
3900 #endif
3901 
3902  return(compute_entropy(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,u));
3903  }
3904 
3905 }
3906 
3908 void get_EOS_parms_simple(int*numparms, int i, int j, int k, int loc, FTYPE *parlist)
3909 {
3910 
3911  get_EOS_parms(WHICHEOS,numparms, GLOBALMAC(EOSextraglobal,i,j,k),parlist);
3912 
3913 
3914 }
3915 
3917 void fix_primitive_eos_scalars_simple(int i, int j, int k, int loc, FTYPE *pr)
3918 {
3919 
3920  fix_primitive_eos_scalars(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),pr);
3921 
3922 
3923 }
3924 
3925 FTYPE compute_temp_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3926 {
3927 
3928  return(compute_temp(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k),rho,u));
3929 
3930 }
3931 
3932 
3933 int get_extrasprocessed_simple(int doall, int i, int j, int k, int loc, FTYPE *pr, FTYPE *extras, FTYPE *processed)
3934 {
3935 
3936  return(get_extrasprocessed(WHICHEOS,1, GLOBALMAC(EOSextraglobal,i,j,k), GLOBALMAC(pdump,i,j,k), extras, processed));
3937 
3938 }
3939 
3940 
3942 FTYPE compute_u_from_entropy_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE entropy)
3943 {
3944 
3945  // unlike inversion, require non-NaN entropy, so force rho,u to be positive
3946  if(rho<SMALL) rho=SMALL;
3947  // entropy can be any value
3948 
3949  return(compute_u_from_entropy(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k), rho, entropy));
3950 
3951 }
3952 
3953 FTYPE compute_qdot_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3954 {
3955 
3956  return(compute_qdot(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k), rho, u));
3957 
3958 }
3959 
3960 FTYPE dpdrho0_rho0_u_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3961 {
3962 
3963  return(dpdrho0_rho0_u(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k), rho, u));
3964 
3965 }
3966 
3967 FTYPE dpdu_rho0_u_simple(int i, int j, int k, int loc, FTYPE rho, FTYPE u)
3968 {
3969 
3970  return(dpdu_rho0_u(WHICHEOS,GLOBALMAC(EOSextraglobal,i,j,k), rho, u));
3971 
3972 }