HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
flux.c
Go to the documentation of this file.
1 
11 #include "decs.h"
12 
13 
14 
15 
16 static void leftrightcompute(int i, int j, int k, int dir, int is, int ie, int js, int je, int ks, int ke, int *computewithleft, int *computewithright);
17 
18 
19 
20 
21 
23 static void leftrightcompute(int i, int j, int k, int dir, int is, int ie, int js, int je, int ks, int ke, int *computewithleft, int *computewithright)
24 {
25 
26 #if(MERGEDC2EA2CMETHOD)
27  // if doing merged method, then expanded "flux" calculation to get state in full (i.e. left,cent,right) in the "-1" and "N" cells
28  if(dir==1 && (i==is) || dir==2 && (j==js) || dir==3 && (k==ks)){ *computewithleft=0; *computewithright=1; }
29  else if(dir==1 && (i==ie) || dir==2 && (j==je) || dir==3 && (k==ke)){ *computewithleft=1; *computewithright=0; }
30  else{ *computewithleft=1; *computewithright=1; }
31 #else
32  // normal routine when always get final dissipative flux
33  *computewithleft=1; *computewithright=1;
34 #endif
35 
36 
37 }
38 
39 
40 
41 
42 
44 int fluxcalc(int stage,
45  int initialstep, int finalstep,
46  FTYPE (*pr)[NSTORE2][NSTORE3][NPR],
47  FTYPE (*pstag)[NSTORE2][NSTORE3][NPR],
48  FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP],
50  FTYPE (*F1)[NSTORE2][NSTORE3][NPR+NSPECIAL],
51  FTYPE (*F2)[NSTORE2][NSTORE3][NPR+NSPECIAL],
52  FTYPE (*F3)[NSTORE2][NSTORE3][NPR+NSPECIAL],
53  FTYPE *CUf,
54  FTYPE *CUnew,
55  SFTYPE fluxdt,
56  SFTYPE fluxtime,
57  FTYPE *ndt1,
58  FTYPE *ndt2,
59  FTYPE *ndt3
60  )
61 {
62  int fluxcalc_flux(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int *Nvec, FTYPE (*dqvec[NDIM])[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, SFTYPE time, FTYPE *ndtvec[NDIM], struct of_loop *cent2faceloop);
63  void fix_flux(FTYPE (*pr)[NSTORE2][NSTORE3][NPR],FTYPE (*F1)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*F2)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*F3)[NSTORE2][NSTORE3][NPR+NSPECIAL]) ;
64  FTYPE (*dqvec[NDIM])[NSTORE2][NSTORE3][NPR2INTERP];
65  FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL];
66  FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL];
67  FTYPE (**ptrfluxvec)[NSTORE2][NSTORE3][NPR+NSPECIAL];
68  FTYPE *ndtvec[NDIM];
69  int Nvec[NDIM];
70  int flux_point2avg(int stage, int whichmaorem, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecother[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
71  void preinterp_flux_point2avg(void);
72  int i,j,k;
73  int pl,pliter;
74  int dir;
75  int fluxEM2flux4EMF(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
76  int fluxsum(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
77  int cleanup_fluxes(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
78  int zero_out_fluxes(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
79  int zero_out_emf_fluxes(int *Nvec, FTYPE (*fluxvecem[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
80 
81  // face2faceloop[dir=facedir] and face2cornloop[EMFdir=edgedir][EMFodir1][EMFodir2]
82  // face2centloop separately used during separate part of advance()
83  struct of_loop cent2faceloop[NDIM],face2cornloop[NDIM][NDIM][NDIM];
84 
85 
87  //
88  // SETUP dimensionality
89  //
91 
92  fluxvec[1]=F1;
93  fluxvec[2]=F2;
94  fluxvec[3]=F3;
95 
96  fluxvecEM[1]=GLOBALPOINT(F1EM); // more temporary than F1,F2,F3, so don't pass to here and just keep global
97  fluxvecEM[2]=GLOBALPOINT(F2EM);
98  fluxvecEM[3]=GLOBALPOINT(F3EM);
99 
100  dqvec[1]=GLOBALPOINT(dq1);
101  dqvec[2]=GLOBALPOINT(dq2);
102  dqvec[3]=GLOBALPOINT(dq3);
103 
104  ndtvec[1]=ndt1;
105  ndtvec[2]=ndt2;
106  ndtvec[3]=ndt3;
107 
108  Nvec[1]=N1;
109  Nvec[2]=N2;
110  Nvec[3]=N3;
111 
112  if(splitmaem) ptrfluxvec=fluxvecEM;
113  else ptrfluxvec=fluxvec;
114 
115 
117  //
118  // Zero-out fluxes so can easily update full region in advance.c without special conditions
119  //
121  // zero_out_fluxes(Nvec,ptrfluxvec); // NOT FOR NOW
122 
123 
124 
125  // Below no longer needed since always zero-out all fluxes (reverted)
126  // zero-out EMFs if evolving/tracking vector potential so boundary regions appear simple in DUMPS when showing boundary cells
127  if(TRACKVPOT && FULLOUTPUT!=0){
128  zero_out_emf_fluxes(Nvec,ptrfluxvec);
129  }
130 
132  //
133  // some pre-interplation flux averaging setups
134  //
136  preinterp_flux_point2avg();
137 
138 
139 
141  //
142  // Compute normal flux at face
143  // Involves interpolating CENT -> FACE1,2,3
144  // Final p_l p_r results of interpolation are stored in pl_ct pr_ct if needed by SPLITNPR or FLUXB==FLUXCTSTAG
145  // Wavespeeds may also be stored globally if STOREWAVESPEEDS>0
146  // In all cases wavespeed constraint on timestep is set here
147  //
148  // assume fluxvec is MA only if splitmaem==1
149  //
151 
152  // CUf[2]=current dt to be used on flux
153  fluxcalc_flux(stage, pr, pstag, pl_ct, pr_ct, Nvec, dqvec, fluxvec, fluxvecEM, CUf[2], fluxtime, ndtvec, cent2faceloop);
154 
155 
156 
157 
158 
159 
160 
161 #if(0)
162  // DEBUG:
163  if(Nvec[1]>1) FULLLOOP PLOOP(pliter,pl) MACP1A1(fluxvec,1,i,j,k,pl)+=MACP1A1(fluxvecEM,1,i,j,k,pl);
164  if(Nvec[2]>1) FULLLOOP PLOOP(pliter,pl) MACP1A1(fluxvec,2,i,j,k,pl)+=MACP1A1(fluxvecEM,2,i,j,k,pl);
165  if(Nvec[3]>1) FULLLOOP PLOOP(pliter,pl) MACP1A1(fluxvec,3,i,j,k,pl)+=MACP1A1(fluxvecEM,3,i,j,k,pl);
166 #endif
167 
168 
169 
171  //
172  // FIXFLUX
173  //
175 
176  if(FIXUPFLUX && splitmaem==0){ // for now can't use fix_flux with splitmaem since it resets field part to 0 that I'm using as diagonal gas pressure term
177  fix_flux(pr, fluxvec[1], fluxvec[2], fluxvec[3]);
178  if(splitmaem) fix_flux(pr, fluxvecEM[1], fluxvecEM[2], fluxvecEM[3]);
179 #if(PRODUCTION==0)
180  trifprintf( "x");
181 #endif
182  }
183 
184 
186  //
187  // ADJUST FLUXES
188  //
190 
191  if(ADJUSTFLUX){
192  extern void adjust_flux(SFTYPE fluxtime,FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE (*F1)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*F2)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*F3)[NSTORE2][NSTORE3][NPR+NSPECIAL]);
193 
194  adjust_flux(fluxtime, pr, fluxvec[1], fluxvec[2], fluxvec[3]);
195 #if(PRODUCTION==0)
196  trifprintf( "q");
197 #endif
198  }
199 
200 
201 
202 
204  //
205  // FLUXCTSTAG -- overwrite field fluxes (emf's) with correct CORN1,2,3 points values
206  //
207  // assumes fluxcalc_flux() above called fluxcalc_standard_4fluxctstag() so pl_ct and pr_ct are set with FACE1,2,3 values of all quantities (including field along dir that comes from pstagscratch[] in this case)
208  //
210  if(FLUXB==FLUXCTSTAG){
211 #if(STOREWAVESPEEDS==0 || USESTOREDSPEEDSFORFLUX==0)
212  dualfprintf(fail_file,"STOREWAVESPEEDS,USESTOREDSPEEDSFORFLUX must be >0 when FLUXB==FLUXCTSTAG\n");
213  // must store because vchar() cannot be computed at CORN since only have partial velocities and partial fields and no densities
214  // really only STOREWAVESPEEDS must be >0, but for now assume both
215  myexit(175106);
216 #endif
217 
218 
219  MYFUN(fluxcalc_fluxctstag(stage, initialstep, finalstep, pr, pstag, pl_ct, pr_ct, GLOBALPOINT(pvbcorninterp), GLOBALPOINT(wspeed), GLOBALPOINT(prc), GLOBALPOINT(pleft), GLOBALPOINT(pright), GLOBALPOINT(fluxstatecent), GLOBALPOINT(fluxstate), GLOBALPOINT(geomcornglobal), Nvec, dqvec, ptrfluxvec, vpot, CUf, CUnew, fluxdt, fluxtime, cent2faceloop, face2cornloop),"flux.c:fluxcalc()", "fluxcalc_fluxctstag", 0);
220 
221  }// end if staggered method where can update A_i directly
222 
223 
224 
225 #if(PRODUCTION==0)
226  trifprintf( "c");
227 #endif
228 
229 
230 
231 #if(0)
232  // DEBUG:
233  FULLLOOP{
234  DIMENLOOP(dir){
235  if(Nvec[dir]>1){
236  PLOOP(pliter,pl){
237  if(pl>=B1 && pl<=B2){
238  if(!isfinite(MACP1A1(fluxvec,dir,i,j,k,pl))){
239  dualfprintf(fail_file,"GOD FLUXA: dir=%d pl=%d i=%d j=%d k=%d\n",dir,pl,i,j,k,MACP1A1(fluxvec,dir,i,j,k,pl));
240  }
241  }
242  }
243  }
244  }
245  }
246 #endif
247 
248 
249 
250 
251 
253  //
254  // convert point FLUXES to surface-averaged fluxes (for field, if FLUXB==FLUXCTSTAG, then should do line integral of emf ENOMARK)
255  //
257  if((interporder[avgscheme[1]]>3) || (interporder[avgscheme[2]]>3) || (interporder[avgscheme[3]]>3)){
258  if(splitmaem){
259  // assume fluxvec is MA only if splitmaem==1
260  //flux_point2avg(stage, ISMAONLY, pr, Nvec, fluxvec,NULL);
261  // below version forces summation of MA+EM for stencil
262  flux_point2avg(stage, ISMAONLY, pr, Nvec, fluxvec,fluxvecEM);
263  flux_point2avg(stage, ISEMONLY, pr, Nvec, fluxvecEM, NULL);
264  }
265  else{
266  flux_point2avg(stage, ISMAANDEM, pr, Nvec, fluxvec,NULL);
267  }
268  }
269 
270 
271 
272 
273 
274 #if(0)
275  // DEBUG: // also helped after flux_point2avg() but not before! -- so higher order code is problem or fed bad data
276  // bound_flux(-1,F1,F2,F3);
277 #endif
278 
279 
280 
282  //
283  // FLUXCT : must come after modifying fluxes so that divb=0 is preserved to machine error
284  // i.e. flux_ct modifies fluxes in special way just before updating field so that divb=0 is conserved
285  // Method is only 2nd order at best since assumes volume average is same as surface average
286  //
288  if((FLUXB==ATHENA1)||(FLUXB==ATHENA2)||(FLUXB==FLUXCTTOTH)||(FLUXB==FLUXCD)){
289 
290  MYFUN(flux_ct(stage, initialstep, finalstep, pr, GLOBALPOINT(emf), GLOBALPOINT(vconemf), GLOBALPOINT(dq1), GLOBALPOINT(dq2), GLOBALPOINT(dq3), ptrfluxvec[1], ptrfluxvec[2], ptrfluxvec[3], vpot, Nvec, CUf, CUnew, fluxdt, fluxtime),"step_ch.c:advance()", "flux_ct",1);
291 
292  }
293 
294 
296  //
297  // sum up MA+EM
298  // if splitmaem==1, then MA and EM split up to this point
299  //
301 
302  if(splitmaem) fluxsum(Nvec, fluxvec,fluxvecEM);
304  //
305  // now fluxvec has MA+EM and fluxvecEM is no longer needed
306  //
308 
309 
310 
312  //
313  // Merged c2e-c2a method
314  //
316  if(MERGEDC2EA2CMETHOD){
317  mergedc2ea2cmethod_compute(Nvec,fluxvec);
318  }
319 
320 
321 
322 
323 
325  //
326  // Clean-up fluxes so zero outside well-defined computational box
327  // Turns out to be easier to clean-up rather than ensure computed in right places
328  //
330  cleanup_fluxes(Nvec,ptrfluxvec);
331 
332 
334  //
335  // DEBUG:
336  //
338 #if(FLUXDUMP==1)
339  // this accounts for final flux
340  FULLLOOP{
341  DIMENLOOP(dir){
342  if(Nvec[dir]>1){
343  PLOOP(pliter,pl) GLOBALMACP0A1(fluxdump,i,j,k,4*NPR + (dir-1)*NPR*5 + NPR*0 + pl)=MACP1A1(fluxvec,dir,i,j,k,pl);
344  }
345  else{
346  PLOOP(pliter,pl) GLOBALMACP0A1(fluxdump,i,j,k,4*NPR + (dir-1)*NPR*5 + NPR*0 + pl)=0.0;
347  }
348  }
349  }
350 #endif
351 
352 
353 
354  // DEBUG: // helped!
355  // bound_prim(-1,F1,NULL,NULL,1);
356  // bound_prim(-1,F2,NULL,NULL,1);
357 
358  // DEBUG: // also helped!
359  //bound_flux(-1,F1,F2,F3);
360 
361 
362  return(0);
363 
364 
365 }
366 
367 
368 
372 int cleanup_fluxes(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL])
373 {
374 
375 
376 
377  // for nowait to matter, has to be on inner loop but outer (dir) loop must be inside the parallel construct since a parallel construct has an impassible barrier. If one put the parallel region inside the outer (dir) loop, the nowait would be useless. Then interior things that depend upon "dir" must be made private, including "dir" itself
378 #pragma omp parallel
379  {
380  int i,j,k;
381  int dir;
382  int pl,pliter;
383  int is,ie,js,je,ks,ke;
384  int B1is,B1ie,B1js,B1je,B1ks,B1ke;
385  int B2is,B2ie,B2js,B2je,B2ks,B2ke;
386  int B3is,B3ie,B3js,B3je,B3ks,B3ke;
387  int loop[NUMFLUXLOOPNUMBERS];
388  // int odir1,odir2;
389  OPENMP3DLOOPVARSDEFINE; OPENMP3DLOOPSETUPFULL; // doesn't depend upon dir, so can be outside DIMENLOOP. However, blockijk must be private, so go ahead and put inside parallel region
390 
391  // pick reference loop as where evolve conserved quantities
392  // must shift since indices not used as arguments to LOOP
399 
400 
401 
402  DIMENLOOP(dir){
403  if(Nvec[dir]>1){
404 
405  // get_odirs(dir,&odir1,&odir2);
406 
407  is=loop[FIS];
408  ie=loop[FIE]+(dir==1)*SHIFT1;
409  js=loop[FJS];
410  je=loop[FJE]+(dir==2)*SHIFT2;
411  ks=loop[FKS];
412  ke=loop[FKE]+(dir==3)*SHIFT3;
413 
414 
415  if(FLUXB==FLUXCTSTAG){
416  // E1: Needed: i==0..N1-1 j=0..N2 k=0..N3
417  // E2: Needed: i==0..N1 j=0..N2-1 k=0..N3
418  // E3: Needed: i==0..N1 j=0..N2 k=0..N3-1
419  // Note Fi[Bi]=0 always and should already be set everywhere
420 
421  // B1
422  B1is=loop[FIS];
423  B1ie=loop[FIE]+(dir==1 || dir==2 || dir==3)*SHIFT1; // for F1[B1],F2[B1]=E3,F3[B1]=E2
424  B1js=loop[FJS];
425  B1je=loop[FJE]+(dir==1 || dir==2)*SHIFT2; // for F1[B1],F2[B1]=E3
426  B1ks=loop[FKS];
427  B1ke=loop[FKE]+(dir==1 || dir==3)*SHIFT3; // for F1[B1],F3[B1]=E2
428 
429  // B2
430  B2is=loop[FIS];
431  B2ie=loop[FIE]+(dir==1 || dir==2)*SHIFT1; // for F1[B2]=E3,F2[B2],F3[B2]=E1
432  B2js=loop[FJS];
433  B2je=loop[FJE]+(dir==1 || dir==2 || dir==3)*SHIFT2; // for F1[B2]=E3,F2[B2],F3[B2]=E1
434  B2ks=loop[FKS];
435  B2ke=loop[FKE]+(dir==2 || dir==3)*SHIFT3; // for F2[B2],F3[B2]=E1
436 
437  // B3
438  B3is=loop[FIS];
439  B3ie=loop[FIE]+(dir==1 || dir==3)*SHIFT1; // for F1[B3]=E2,F3[B3]
440  B3js=loop[FJS];
441  B3je=loop[FJE]+(dir==2 || dir==3)*SHIFT2; // for F1[B3]=E2,F2[B3]=E1,F3[B3]
442  B3ks=loop[FKS];
443  B3ke=loop[FKE]+(dir==1 || dir==2 || dir==3)*SHIFT3; // for F1[B3]=E2,F2[B3]=E1,F3[B3]
444  }
445  else{
446  B1is=B2is=B3is=is;
447  B1ie=B2ie=B3ie=ie;
448  B1js=B2js=B3js=js;
449  B1je=B2je=B3je=je;
450  B1ks=B2ks=B3ks=ks;
451  B1ke=B2ke=B3ke=ke;
452  }
453 
454 
455  // dualfprintf(fail_file,"dir=%d Clean1: is=%d ie=%d js=%d je=%d ks=%d ke=%d\n",dir,is,ie,js,je,ks,ke);
456  // dualfprintf(fail_file,"CleanB1: B1is=%d B1ie=%d B1js=%d B1je=%d B1ks=%d B1ke=%d\n",B1is,B1ie,B1js,B1je,B1ks,B1ke);
457  // dualfprintf(fail_file,"CleanB2: B2is=%d B2ie=%d B2js=%d B2je=%d B2ks=%d B2ke=%d\n",B2is,B2ie,B2js,B2je,B2ks,B2ke);
458  // dualfprintf(fail_file,"CleanB3: B3is=%d B3ie=%d B3js=%d B3je=%d B3ks=%d B3ke=%d\n",B3is,B3ie,B3js,B3je,B3ks,B3ke);
459 
460 
462 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize)) nowait // can nowait since each fluxvec[dir] is set separately
464  OPENMP3DLOOPBLOCK2IJK(i,j,k);
465 
466  // below means we are not within the computational block
467  if(! (i>=is && i<=ie && j>=js && j<=je && k>=ks && k<=ke) ){
468  PLOOPNOB1(pl) MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
469  PLOOPNOB2(pl) MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
470  }
471  if(! (i>=B1is && i<=B1ie && j>=B1js && j<=B1je && k>=B1ks && k<=B1ke) ){
472  pl=B1; MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
473  }
474  if(! (i>=B2is && i<=B2ie && j>=B2js && j<=B2je && k>=B2ks && k<=B2ke) ){
475  pl=B2; MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
476  }
477  if(! (i>=B3is && i<=B3ie && j>=B3js && j<=B3je && k>=B3ks && k<=B3ke) ){
478  pl=B3; MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
479  }
480  }// end 3D loop
481  }// end if doing this dimen
482  }// end over dimens
483  }// end parallel region (no need for added barrier since parallel region has impassible barrier)
484 
485 
486 
487 
488  return(0);
489 
490 }
491 
492 
493 
496 int zero_out_fluxes(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL])
497 {
498 
499 #pragma omp parallel
500  {
501  int i,j,k,pl,pliter;
502  int dir;
504 
505  DIMENLOOP(dir){
506  if(Nvec[dir]>1){
507 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize)) nowait // can nowait since each fluxvec[dir] is set separately
509  OPENMP3DLOOPBLOCK2IJK(i,j,k);
511  PLOOP(pliter,pl) MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
512  }// end over 3D loop
513  }// if dir
514  }// over dirs
515  }// end parallel region (no need for added barrier since parallel region has impassible barrier)
516 
517 
518 
519  return(0);
520 }
521 
525 int zero_out_emf_fluxes(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL])
526 {
527 
528 #pragma omp parallel
529  {
530  int i,j,k,pl,pliter;
531  int dir;
533 
534  DIMENLOOP(dir){
535  if(Nvec[dir]>1){
536 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize)) nowait // can nowait since each fluxvec[dir] is set separately
538  OPENMP3DLOOPBLOCK2IJK(i,j,k);
540  PLOOPBONLY(pl) MACP1A1(fluxvec,dir,i,j,k,pl)=0.0;
541  }// end over 3D loop
542  }// if dir
543  }// over dirs
544  }// end parallel region (no need for added barrier since parallel region has impassible barrier)
545 
546 
547  return(0);
548 }
549 
550 
551 
552 
553 // fill EM version if necessary when having new CT EMFs
554 int fluxEM2flux4EMF(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL])
555 {
556 
557 #pragma omp parallel
558  {
559  int i,j,k,pl,pliter;
560  int dir;
561 
562  if(splitmaem){
563 
565  DIMENLOOP(dir){
566  if(Nvec[dir]>1){
567 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize)) nowait // can nowait since each fluxvec[dir] is set separately
569  OPENMP3DLOOPBLOCK2IJK(i,j,k);
571  PLOOPBONLY(pl) MACP1A1(fluxvecEM,dir,i,j,k,pl)=MACP1A1(fluxvec,dir,i,j,k,pl);
572  }// end over 3D loop
573  }// if dir
574  }// over dirs
575  }// end if splitmaem
576  }// end parallel region
577 
578 
579  return(0);
580 }
581 
583 int fluxsum_old(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL])
584 {
585 
586 #pragma omp parallel
587  {
588  int i,j,k,pl,pliter;
589  int dir;
590 
591  if(splitmaem){
592 
594  DIMENLOOP(dir){
595  if(Nvec[dir]>1){
596 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize)) nowait // can nowait since each fluxvec[dir] is set separately
598  OPENMP3DLOOPBLOCK2IJK(i,j,k);
600  PLOOP(pliter,pl) MACP1A1(fluxvec,dir,i,j,k,pl)+=MACP1A1(fluxvecEM,dir,i,j,k,pl);
601  }// end over 3D loop
602  }// end if dir
603  }// end over dirs
604  }// end if splitmaem
605  }// end parallel region
606 
607 
608  return(0);
609 }
610 
611 
613 int fluxsum(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL])
614 {
615 
616 
617 #pragma omp parallel
618  {
619  int i,j,k,pl,pliter;
620  int dir;
621 
622  if(splitmaem){
623 
625 
626  DIMENLOOP(dir){
627  if(Nvec[dir]>1){
628 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize)) nowait // can nowait since each fluxvec[dir] is set separately
630  OPENMP3DLOOPBLOCK2IJK(i,j,k);
632 #if(SPLITPRESSURETERMINFLUXMA)
633  // add diagonal pressure term back to normal FLUX term
634  MACP1A1(fluxvec,dir,i,j,k,UU+dir)+=MACP1A1(fluxvec,dir,i,j,k,FLUXSPLITPMA(dir));
635  // reset temporary storage
636  MACP1A1(fluxvec,dir,i,j,k,FLUXSPLITPMA(dir))=0.0;
637 #endif
638 #if(SPLITPRESSURETERMINFLUXEM)
639  // add diagonal pressure term back to normal FLUX term
640  MACP1A1(fluxvec,dir,i,j,k,UU+dir)+=MACP1A1(fluxvecEM,dir,i,j,k,FLUXSPLITPEM(dir));
641  // reset temporary storage
642  MACP1A1(fluxvecEM,dir,i,j,k,FLUXSPLITPEM(dir))=0.0;
643 #endif
644  // now do normal addition
645  PLOOP(pliter,pl) MACP1A1(fluxvec,dir,i,j,k,pl)+=MACP1A1(fluxvecEM,dir,i,j,k,pl);
646  }// over 3D LOOP
647  }// if dir
648  }// over dirs
649  }// end if splitmaem
650  }// end parallel region
651 
652 
653  return(0);
654 }
655 
656 
657 
658 
659 
660 
662 int fluxcalc_flux(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int *Nvec, FTYPE (*dqvec[NDIM])[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*fluxvecEM[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, SFTYPE time, FTYPE *ndtvec[NDIM], struct of_loop *cent2faceloop)
663 {
664  int fluxcalc_flux_1d(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, FTYPE *ndt, struct of_loop *cent2faceloop, int *didassigngetstatecentdata );
665  int dir;
666  int idel, jdel, kdel, face;
667  int is, ie, js, je, ks, ke;
668  int didassigngetstatecentdata;
669 
670 
672  //
673  // LOOP OVER DIMENSIONS interpolating within each dimension separately for that flux -- assumes flux determined by 1-D Riemann problem
674  //
676  didassigngetstatecentdata=0;
677 
678  // OPENMPOPTMARK: Can actually do each direction independently, so able to parallelize this! (But would required, e.g., an array per dir for (e.g.) pleft/pright,wspeedtemp (global variable used inside for temp space for rescale(). *ndt is done per-dir, so that's ok (it would be fine already since using "critical" that applies to *all* threads not just one team))).
679  // Note also ok to do each dir separately with FLUXB==FLUXCTSTAG.
680  // OPENMPOPTMARK: Otherwise, looks doable.
681 
682  DIMENLOOP(dir){
683 
684  // set dimension having no influence on dt by default
685  *(ndtvec[dir])=BIG;
686 
687  // don't skip dimension if doesn't exist, will be taken care of inside fluxcalc_flux_1d()
688 
689 
690  // get loop details
691  idel = fluxloop[dir][FIDEL];
692  jdel = fluxloop[dir][FJDEL];
693  kdel = fluxloop[dir][FKDEL];
694  face = fluxloop[dir][FFACE];
695 
696  //loop over the interfaces where fluxes are computed -- atch, useCOMPZSLOOP( is, ie, js, je, ks, ke ) { ... }
697  is=fluxloop[dir][FIS];
698  ie=fluxloop[dir][FIE];
699  js=fluxloop[dir][FJS];
700  je=fluxloop[dir][FJE];
701  ks=fluxloop[dir][FKS];
702  ke=fluxloop[dir][FKE];
703 
704 
705  MYFUN(fluxcalc_flux_1d(stage, pr, pstag, pl_ct, pr_ct, dir, time, is, ie, js, je, ks, ke, idel, jdel, kdel, face, dqvec[dir], fluxvec[dir], fluxvecEM[dir], CUf, ndtvec[dir], &cent2faceloop[dir], &didassigngetstatecentdata),"flux.c:fluxcalc()", "fluxcalc_flux_1d", dir);
706 
707 #if(PRODUCTION==0)
708  trifprintf("%d",dir);
709 #endif
710  }// end DIMENLOOP(dir)
711 
712 
713 
714 
715 
716 
718  //
719  // set per-cell minimum for dt
720  //
722  if(PERCELLDT){
723  FTYPE ndtveclocal[NDIM];
724 
725  {
726  int dimen;
727  // set dimension having no influence on dt by default
728  DIMENLOOP(dimen){
729  *(ndtvec[dimen])=BIG;
730  ndtveclocal[dimen]=BIG;
731  }
732  }
733 
734  // whether dimension is relevant
735  int doingdimen[NDIM];
736  doingdimen[1]=N1NOT1;
737  doingdimen[2]=N2NOT1;
738  doingdimen[3]=N3NOT1;
739 
740  int dimenorig=1; // choose one dimension to stick things into
741 
742 #pragma omp parallel
743  {
744  int i,j,k;
745  FTYPE wavedt;
746  int dimen;
747 
749 
750 
751 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
753  OPENMP3DLOOPBLOCK2IJK(i,j,k);
754 
755  // get dt for each dimension at each grid point -- but only if dimension is relevant (otherwise stays as BIG and doesn't affect wavedt)
756  DIMENLOOP(dimen) if(doingdimen[dimen]) ndtveclocal[dimen]=GLOBALMACP0A1(dtijk,i,j,k,dimen);
757 
758  if(i<-1 || j<-1 || k<-1 || i>N1 || j>N2 || k>N3 || i<0 && j<0 || i<0 && k<0 || j<0 && k<0 || i>N1-1 && j>N2-1 || i>N1-1 && k>N3-1 || j>N2-1 && k>N3-1 || ndtveclocal[1] <0.0 || ndtveclocal[2] <0.0 || ndtveclocal[3] <0.0) continue; // avoid too deep into boundary or if never set. // SUPERGODMARK: KINDA HACK, can improve.
759 
760  // set local per-cell dt
761  // sum of inverses is proper for unsplit scheme based upon split interpolations/fluxes.
762  wavedt = MINDTSET(ndtveclocal[1],ndtveclocal[2],ndtveclocal[3]);
763 
764  // use dimen=1 to store result
765  dimen=dimenorig;
766 #pragma omp critical
767  {
768  if (wavedt < *(ndtvec[dimen]) ){
769  *ndtvec[dimen] = wavedt;
770  // below are global so can report when other dt's are reported in advance.c
771  waveglobaldti[dimen]=i;
772  waveglobaldtj[dimen]=j;
773  waveglobaldtk[dimen]=k;
774  }
775  }// end critical region
776  }//end over 3dloopblock
777  }// end over parallel region
778 
779  // store result in all of ndt1,ndt2,ndt3 so have result no matter how many dimensions working on, and just use correctly later.
780  {
781  int dimen;
782  DIMENLOOP(dimen){
783  if(doingdimen[dimen]){
784  *ndtvec[dimen]=*ndtvec[dimenorig];
785  waveglobaldti[dimen]=waveglobaldti[dimenorig];
786  waveglobaldtj[dimen]=waveglobaldtj[dimenorig];
787  waveglobaldtk[dimen]=waveglobaldtk[dimenorig];
788  }
789  }
790  }
791 
792 
793  }// end over doing PERCELLDT
794 
795 
796 
797  return(0);
798 
799 }
800 
801 
802 
805 int fluxcalc_flux_1d(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, FTYPE *ndt, struct of_loop *cent2faceloop, int *didassigngetstatecentdata )
806 {
807  int fluxcalc_standard(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, FTYPE *ndt, struct of_loop *cent2faceloop, int *didassigngetstatecentdata);
808  int fluxcalc_standard_4fluxctstag(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, FTYPE *ndt, struct of_loop *cent2faceloop, int *didassigngetstatecentdata);
809 
810  // int fluxcalc_fluxspliteno(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], int dir, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE *ndt);
811  int Nvec[NDIM];
812  int i,j,k,pl,pliter;
813  int odir1,odir2;
814 
815 
816 
817  if(DOENOFLUX!=ENOFLUXSPLIT){
818 
819  if(FLUXB==FLUXCTSTAG){
820  MYFUN(fluxcalc_standard_4fluxctstag(stage,pr,pstag,pl_ct, pr_ct, dir,time, is, ie, js, je, ks, ke,idel,jdel,kdel,face,dq,F,FEM,CUf,ndt,cent2faceloop,didassigngetstatecentdata),"flux.c:fluxcalc_flux_1d()", "fluxcalc_standard_4fluxctstag()", 1);
821  }
822  else{
823  // use older code that doesn't store into pl_ct and pr_ct since not needed and then waste of memory
824  MYFUN(fluxcalc_standard(stage,pr,pstag,pl_ct, pr_ct, dir,time,is, ie, js, je, ks, ke,idel,jdel,kdel,face,dq,F,FEM,CUf,ndt,cent2faceloop,didassigngetstatecentdata),"flux.c:fluxcalc_flux_1d()", "fluxcalc_standard()", 1);
825  }
826  }
827  else{
828  //MYFUN(fluxcalc_fluxspliteno(stage,pr,dir,is, ie, js, je, ks, ke,idel,jdel,kdel,face,dq,F,FEM,CUf,ndt),"flux.c:fluxcalc_flux_1d()", "fluxcalc_fluxspliteno()", 1);
829  }
830 
831 
832 
834  //
835  // ensure flux of field set correctly to 0 in 1D
836  //
837  // if 1D in z and x, then no Ey so no F3[B1]
838  // if 1D in z and y, then no Ex so no F3[B2]
839  //
840  // Stupid: This is automatically done since if no z-dir, then F3 not even used
841  //
843 
844  /*
845  Nvec[1]=N1;
846  Nvec[2]=N2;
847  Nvec[3]=N3;
848 
849 
850  odir1=dir%3+1;
851  odir2=(dir+1)%3+1;
852  if(splitmaem==0){
853  if(Nvec[dir]==1 && Nvec[odir1]==1) COMPFULLLOOP MACP0A1(F,i,j,k,B1-1+odir1)=0.0;
854  if(Nvec[dir]==1 && Nvec[odir2]==1) COMPFULLLOOP MACP0A1(F,i,j,k,B1-1+odir2)=0.0;
855  COMPFULLLOOP MACP0A1(F,i,j,k,B1-1+dir)=0.0; // flux along field is always 0 due to antisymmetry of Faraday/Maxwell
856  }
857  else{
858  // only need to change FEM since above F doesn't contain this EMF in this case
859  if(Nvec[dir]==1 && Nvec[odir1]==1) COMPFULLLOOP MACP0A1(FEM,i,j,k,B1-1+odir1)=0.0;
860  if(Nvec[dir]==1 && Nvec[odir2]==1) COMPFULLLOOP MACP0A1(FEM,i,j,k,B1-1+odir2)=0.0;
861  COMPFULLLOOP MACP0A1(FEM,i,j,k,B1-1+dir)=0.0; // flux along field is always 0 due to antisymmetry of Faraday/Maxwell
862  // don't reset field part of MA flux since using that for other purposes (diagonal pressure term for now)
863  }
864  */
865 
866 
867 
868  return(0);
869 
870 }
871 
873 void set_normal_realisinterp(int *realisinterp)
874 {
875 
876 
877  // real means normal primitive list = {rho,u,v1,v2,v3,B1,B2,B3} with v^i as WHICHVEL velocity
878  // check:
879 
880  if(npr2interpstart==0 && npr2interpend==7 &&
881  npr2interplist[RHO]==RHO &&
882  npr2interplist[UU]==UU &&
883  npr2interplist[U1]==U1 &&
884  npr2interplist[U2]==U2 &&
885  npr2interplist[U3]==U3 &&
886  npr2interplist[B1]==B1 &&
887  npr2interplist[B2]==B2 &&
889  ){
890 
891  // 1 here stands for NPR2INTERP type of loop
892  // only do if some type of interpolation to be done
893  *realisinterp=(RESCALEINTERP==0 || VARTOINTERP==PRIMTOINTERP);
894  }
895  else{
896  *realisinterp=0; // must be forced to be zero
897  }
898 
899 
900 
901 }
902 
903 
904 
905 
907 void rescale_calc_full(int dir,FTYPE (*pr)[NSTORE2][NSTORE3][NPR],FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR])
908 {
909 
911 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOMINTERP // generally requires full information
912  {
913  int i,j,k;
914  struct of_geom geomdontuse;
915  struct of_geom *ptrgeom=&geomdontuse;
917 
918  // generally ptr's are different inside parallel block
919  ptrgeom=&geomdontuse;
920 
921 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
923  OPENMP3DLOOPBLOCK2IJK(i,j,k);
924 
925  // get geometry for center pre-interpolated values
926  get_geometry(i, j, k, CENT, ptrgeom);
927  // assume no need for a guess to p2interp to get pr (consistent with no unrescale being done after interpolation)
928  if(npr2interpstart<=npr2interpend) rescale(DORESCALE,dir,MAC(pr,i,j,k),ptrgeom,MAC(p2interp,i,j,k));
929  }// end COMPFULLLOOP
930  }// end parallel region
931 
932 
933 }
934 
935 
936 
937 
938 
940 int fluxcalc_standard(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time,int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, FTYPE *ndt, struct of_loop *cent2faceloop, int *didassigngetstatecentdata)
941 {
942  void slope_lim(int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*primreal)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop);
943  int getplpr(int dir, SFTYPE time, int idel, int jdel, int kdel, int i, int j, int k, struct of_geom *geom, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE *p2interp_l, FTYPE *p2interp_r, FTYPE *p_l, FTYPE *p_r);
944  FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP];
945  // int odir1,odir2;
946  int Nvec[NDIM];
947  int realisinterp;
948  int dointerpolation;
949  void do_noninterpolation_dimension(int whichfluxcalc, int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop, int *didassigngetstatecentdata);
950  void compute_and_store_fluxstate(int dimen, int isleftright, int i, int j, int k, struct of_geom *geom, FTYPE *pr);
951 
952 
953 
954 
956  //
957  // setup 1D reduction of EMF,flux calculation
958  // here dir is face dir
959  // odir1=dir%3+1;
960  // odir2=(dir+1)%3+1;
961  Nvec[1]=N1;
962  Nvec[2]=N2;
963  Nvec[3]=N3;
964 
965 
966  set_normal_realisinterp(&realisinterp);
967 
968 
969 
971  //
972  // skip to next dir if no such dimension
973  //
975 
976  // if nothing to interpolate, then quit
977  if(npr2interpstart<=npr2interpend && Nvec[dir]>1){
978  dointerpolation=1;
979  }
980  else{
981  // just get loops and copy over to gp_?
982  dointerpolation=0;
983 
984  //do limited number of things when not interpolating that dimension
985  do_noninterpolation_dimension(ORIGINALFLUXCALC, dointerpolation, realisinterp, dir, idel, jdel, kdel, pr, pl_ct, pr_ct, cent2faceloop, didassigngetstatecentdata);
986 
987  // skip real interpolation since no variation in that direction
988  return(0);
989  }
990 
991 
992 
993 
995  //
996  // setup wavedt
997  //
999  waveglobaldti[dir]=-100;
1000  waveglobaldtj[dir]=-100;
1001  waveglobaldtk[dir]=-100;
1002 
1003 
1004 
1006  //
1007  // rescale before interpolation
1008  //
1010 #if(RESCALEINTERP)
1012  // assume if DOEXTRAINTERP==1, then must get here
1013  p2interp=GLOBALPOINT(prc); // it's different
1014  }
1015  rescale_calc_full(dir,pr,p2interp);
1016 #else
1017  p2interp=pr; // it's itself
1018 #endif
1019 
1020 
1021 
1022  // STOREWAVESPEEDS==0 : use very local estimate at fluxes FACE?
1023  // STOREWAVESPEEDS==1 : use original pre-computed (just below) wavespeed at CENT that is "max-averaged" to FACE?
1024  // STOREWAVESPEEDS==2 : use very local estimate at fluxes FACE?, but compute and store during loop
1025  if(STOREWAVESPEEDS==1){
1026 
1027 #if(SPLITNPR)
1028  // update wavespeed on FIRST pass
1029  if(advancepassnumber<=0)
1030 #endif
1031  {
1032  MYFUN(get_global_wavespeeds_full(dir,is,ie,js,je,ks,ke,idel,jdel,kdel,POINT(pr),GLOBALPOINT(wspeed)),"flux.c:fluxcalc_standard()", "get_global_wavespeeds_full()", 0);
1033  }
1034  } // end if storing wavespeeds
1035 
1036 
1037 
1038 
1039 
1040 
1041 
1042 
1044  //
1045  // evaluate slopes (dq) or get pleft/pright of (possibly rescaled) primitive variables
1046  // c2e reconstruction: p2interp -> pleft & pright (indexed by grid cell #) -- atch comment
1047  //
1048  // pleft,pright also considered very temporary and so ok to be global (unless some computational overlapping is desired)
1049  //
1051  slope_lim(dointerpolation,realisinterp,dir,idel,jdel,kdel,pr,p2interp,dq,GLOBALPOINT(pleft),GLOBALPOINT(pright),cent2faceloop);
1052 
1053 
1054 
1055 
1056 
1057 
1058 
1060  //
1061  // flux loop : Extra "expand" zone for the purpose of averaging flux to get emf at corner. Only used by field components, see flux_ct().
1062  // This loop is over interfaces where fluxes are evaluated -- atch
1063  //
1065 
1066  //#if((SIMULBCCALC==2)&&(TYPE2==1))
1067  // COMPFZLOOP(is,js,ks){
1068  //#else
1069  // COMPZSLOOP( is, ie, js, je, ks, ke ) {{
1070 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOM // requires full information
1071  {
1072  int i,j,k,pl,pliter;
1073  struct of_geom geomdontuse;
1074  struct of_geom *ptrgeom=&geomdontuse;
1075  FTYPE p_l[NPR2INTERP], p_r[NPR2INTERP];
1076  FTYPE pstore_l[NPR2INTERP],pstore_r[NPR2INTERP];
1077  FTYPE *p2interp_l,*p2interp_r;
1078  FTYPE dtij;
1079  FTYPE ctop,ctoprad;
1080  int computewithleft,computewithright;
1081 
1082  OPENMP3DLOOPVARSDEFINE; OPENMP3DLOOPSETUP(is,ie,js,je,ks,ke);
1083 
1084  // Setup rescale pointer reference
1085 #if(RESCALEINTERP)
1086  p2interp_l=pstore_l; // then need separate storage
1087  p2interp_r=pstore_r;
1088 #else
1089  p2interp_l=p_l; // p2interp_? is final p_?
1090  p2interp_r=p_r;
1091 #endif
1092 
1093 
1094 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1096  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1097 
1098 
1099 
1101  //
1102  // get the geometry for the flux face
1103  //
1105  get_geometry(i, j, k, face, ptrgeom);
1106 
1107 
1109  //
1110  // use p2interp,dq,pleft,pright to get p_l and p_r
1111  //
1113 
1115  MYFUN(getplpr(dir,time,idel,jdel,kdel,i,j,k,ptrgeom,pr,pstag,p2interp,dq,GLOBALPOINT(pleft),GLOBALPOINT(pright),p2interp_l,p2interp_r,p_l,p_r),"flux.c:fluxcalc_standard()", "getplpr", 1);
1116 #if(SPLITNPR || FIELDSTAGMEM)
1117  // then means there is going to be a second pass, so store into memory
1118  PINTERPLOOP(pliter,pl){
1119  MACP1A1(pl_ct,dir,i,j,k,pl)=p_l[pl];
1120  MACP1A1(pr_ct,dir,i,j,k,pl)=p_r[pl];
1121  }
1122  PNOTINTERPLOOP(pliter,pl){ // restore those things didn't interpolate
1123  p_l[pl]=MACP1A1(pl_ct,dir,i,j,k,pl);
1124  p_r[pl]=MACP1A1(pr_ct,dir,i,j,k,pl);
1125  }
1126 #endif
1127  }
1128  else{
1129 #if(SPLITNPR || FIELDSTAGMEM)
1130  // GODMARK: for now assume interpolations either all done or none done, else need exclusion list for interpolations
1131  // then just get from memory
1132  PLOOPALLINTERP(pl){
1133  p_l[pl]=MACP1A1(pl_ct,dir,i,j,k,pl);
1134  p_r[pl]=MACP1A1(pr_ct,dir,i,j,k,pl);
1135  }
1136 #endif
1137 #if(SPLITNPR==0 || FIELDSTAGMEM==0)
1138  dualfprintf(fail_file,"Should not be using gp_? in flux.c when SPLITNPR==0 or FIELDSTAGMEM==0\n");
1139  myexit(16760276);
1140 #endif
1141  }
1142 
1143 
1144 
1145  // determine whether should compute things using left/right states
1146  leftrightcompute(i, j, k, dir, is, ie, js, je, ks, ke, &computewithleft, &computewithright);
1147 
1148 
1149 
1151  //
1152  // Compute and Store (globally) the get_state() data for the flux positions to avoid computing later
1153  //
1155 #if(STOREFLUXSTATE)
1156  if(computewithleft) compute_and_store_fluxstate(dir, ISLEFT, i, j, k, ptrgeom, p_l);
1157  if(computewithright) compute_and_store_fluxstate(dir, ISRIGHT, i, j, k, ptrgeom, p_r);
1158  // now flux_compute() and other flux-position-related things will obtain get_state() data for p_l and p_r from global arrays
1159 #endif
1160 
1161 
1162 
1163  if(computewithleft&&computewithright){
1164 
1166  //
1167  // actually compute the dissipative flux
1168  //
1170 
1171  if(splitmaem==0){
1172  MYFUN(flux_compute_general(i, j, k, dir, ptrgeom, CUf, MAC(pr,i,j,k), p_l, p_r, MAC(F,i,j,k), &ctop),"step_ch.c:fluxcalc()", "flux_compute", 1);
1173  }
1174  else{
1175  MYFUN(flux_compute_splitmaem(i, j, k, dir, ptrgeom, CUf, MAC(pr,i,j,k), p_l, p_r, MAC(F,i,j,k), MAC(FEM,i,j,k), &ctop),"step_ch.c:fluxcalc()", "flux_compute", 1);
1176  }
1177 
1178 
1180  //
1181  // evaluate restriction on timestep
1182  //
1184  // below is old before new grid sectioning
1185  //#if( (DOEVOLVEMETRIC || DOSELFGRAVVSR) && (RESTRICTDTSETTINGINSIDEHORIZON==2))
1186  // avoid limiting dt if inside horizon
1187  // GODMARK: can only do this if boundary condition does not drive solution's dt behavior
1188  // if(WITHINENERREGION(enerposreg[OUTSIDEHORIZONENERREGION],i,j,k))
1189  //#endif
1190 
1191 
1193  // set dt for this cell in this direction
1194  dtij = cour * dx[dir] / ctop;
1195 
1196 
1198  //
1199  // save minimum dt
1200  //
1202  if(PERCELLDT==0){
1203  // only set timestep if in computational domain or just +-1 cell beyond. Don't go further since end up not really using that flux or rely on the stability of fluxes beyond that point.
1204  // Need +-1 in case flow is driven by injection boundary conditions rather than what's on grid
1205  if(WITHINACTIVESECTIONEXPAND1(i,j,k)){
1206 #pragma omp critical
1207  {// *ndt and waveglobaldt's have to have blocked write access for OpenMP
1208  if (dtij < *ndt){
1209  *ndt = dtij;
1210  // below are global so can report when other dt's are reported in advance.c
1211  waveglobaldti[dir]=i;
1212  waveglobaldtj[dir]=j;
1213  waveglobaldtk[dir]=k;
1214  }
1215  }// end critical region
1216  }// end if within dt-setting section
1217  }
1218  else{
1219  GLOBALMACP0A1(dtijk,i,j,k,dir) = dtij;
1220  }
1221 
1222 
1223 
1224 
1225  }// end if doing computing using both left+right states (required also for ctop to exist)
1226 
1227 
1228  }// end 3D loop
1229  }// end parallel region
1230 
1231 
1232 
1233 
1234  return (0);
1235 }
1236 
1237 
1238 
1239 
1240 
1241 
1245 void do_noninterpolation_dimension(int whichfluxcalc, int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop, int *didassigngetstatecentdata)
1246 {
1247  int i,j,k;
1248  int pl,pliter;
1249  struct of_geom geomdontuse;
1250  struct of_geom *ptrgeom=&geomdontuse;
1251  void slope_lim(int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*primreal)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop);
1252  void slope_lim_cent2face(int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*primreal)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop);
1253  void compute_and_store_fluxstate(int dimen, int isleftright, int i, int j, int k, struct of_geom *geom, FTYPE *pr);
1254  void compute_and_store_fluxstate_assign(int dimeninput, int dimenoutput, int isleftrightinput, int isleftrightoutput, int i, int j, int k);
1255 
1256 
1257  if(FLUXB==FLUXCTSTAG){
1258  // if storing pl_ct and pr_ct, then copy 1D result in case used in some way not associated with whether dimension exists or not (not expensive)
1259  // For example, this is used for FLUXCTSTAG method in case dimension doesn't exist (Nvec[dir]==1) but still access gp_{l,r} instead of special conditions
1261  copy_3dnpr2interp_2ptrs_fullloop(pr,pl_ct[dir],pr_ct[dir]);
1262  }
1263 
1264 
1265  if(SPLITNPR||FLUXB==FLUXCTSTAG){
1266  // just get loop information
1267  if(whichfluxcalc==ORIGINALFLUXCALC){
1268  slope_lim(dointerpolation, realisinterp,dir,idel,jdel,kdel,NULL,NULL,NULL,NULL,NULL,cent2faceloop);
1269  }
1270  else{
1271  slope_lim_cent2face(dointerpolation, realisinterp,dir,idel,jdel,kdel,NULL,NULL,NULL,NULL,NULL,cent2faceloop);
1272  }
1273  }
1274 
1275 
1276 }
1277 
1278 
1279 
1283 int fluxcalc_standard_4fluxctstag(int stage, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*F)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE (*FEM)[NSTORE2][NSTORE3][NPR+NSPECIAL], FTYPE CUf, FTYPE *ndt, struct of_loop *cent2faceloop, int *didassigngetstatecentdata)
1284 {
1285  int interpolate_prim_cent2face(int stage, int realisinterp, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop);
1286  // int odir1,odir2;
1287  int Nvec[NDIM];
1288  int realisinterp;
1289  int dointerpolation;
1290  void do_noninterpolation_dimension(int whichfluxcalc, int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop, int *didassigngetstatecentdata);
1291 
1292 
1293 
1294 
1295 
1297  //
1298  // setup 1D reduction of EMF,flux calculation
1299  // here dir is face dir
1300  // odir1=dir%3+1;
1301  // odir2=(dir+1)%3+1;
1302  Nvec[1]=N1;
1303  Nvec[2]=N2;
1304  Nvec[3]=N3;
1305 
1306 
1307  // only do interpolation if some type of interpolation to be done
1308  set_normal_realisinterp(&realisinterp);
1309  if(FLUXB==FLUXCTSTAG){
1310  realisinterp=0; // override since not interpolating p[B1+dir-1]
1311  }
1312 
1313 
1315  //
1316  // skip to next dir if no such dimension
1317  //
1319  if(npr2interpstart<=npr2interpend && Nvec[dir]>1){
1320  dointerpolation=1;
1321  }
1322  else{
1323  // just get loops, nothing to copy
1324  dointerpolation=0;
1325 
1326  //do limited number of things when not interpolating that dimension
1327  do_noninterpolation_dimension(NEWFLUXCALC, dointerpolation, realisinterp, dir, idel, jdel, kdel, pr, pl_ct, pr_ct, cent2faceloop,didassigngetstatecentdata);
1328 
1329  // nothing else to do
1330  return(0);
1331  }
1332 
1333 
1334 
1335 
1336 
1337 
1339  //
1340  // setup wavedt
1341  //
1343  waveglobaldti[dir]=-100;
1344  waveglobaldtj[dir]=-100;
1345  waveglobaldtk[dir]=-100;
1346 
1347 
1348 
1349 
1351  //
1352  // get wavespeeds if storing
1353  //
1355 
1356  if(STOREWAVESPEEDS==1){
1357 #if(SPLITNPR)
1358  // update wavespeed on FIRST pass
1359  if(advancepassnumber<=0)
1360 #endif
1361  {
1362  MYFUN(get_global_wavespeeds_full(dir,is,ie,js,je,ks,ke,idel,jdel,kdel,POINT(pr),GLOBALPOINT(wspeed)),"flux.c:fluxcalc_standard()", "get_global_wavespeeds_full()", 0);
1363  }
1364  } // end if storing wavespeeds
1365 
1366 
1367 
1368 
1369 
1370 
1372  //
1373  // obtain pl_ct and pr_ct (point face quantities) from pr (point centered quantity)
1374  //
1376  interpolate_prim_cent2face(stage, realisinterp, pr, pstag, pl_ct, pr_ct, dir, time, is, ie, js, je, ks, ke, idel, jdel, kdel, face, dq, cent2faceloop);
1377 
1378 
1379 
1380 
1381 
1383  //
1384  // flux loop : Extra "expand" zone for the purpose of averaging flux to get emf at corner. Only used by field components, see flux_ct().
1385  // This loop is over interfaces where fluxes are evaluated -- atch
1386  //
1388 
1389  //#if((SIMULBCCALC==2)&&(TYPE2==1))
1390  // COMPFZLOOP(is,js,ks)
1391  //#else
1392  //#endif
1394 #if(STOREFLUXSTATE)
1395 #pragma omp parallel // then flux_compute() below uses *stored* state already
1396 #else
1397 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOM // requires full information
1398 #endif
1399  {
1400  int i, j, k;
1401  FTYPE dtij;
1402  FTYPE ctop;
1403  struct of_geom geomdontuse;
1404  struct of_geom *ptrgeom=&geomdontuse;
1405  int computewithleft,computewithright;
1406 
1407  OPENMP3DLOOPVARSDEFINE; OPENMP3DLOOPSETUP(is,ie,js,je,ks,ke);
1408 
1409  // generally ptr's are different inside parallel block
1410  ptrgeom=&geomdontuse;
1411 
1412 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1414  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1415 
1416 
1417 
1418  // determine whether should compute things using left/right states
1419  leftrightcompute(i, j, k, dir, is, ie, js, je, ks, ke, &computewithleft, &computewithright);
1420 
1421 
1422 
1423 
1424  if(computewithleft&&computewithright){
1425 
1427  //
1428  // get the geometry for the flux face
1429  //
1431  get_geometry(i, j, k, face, ptrgeom); // OPTMARK: Seems should put back together interpolate_prim_cent2face() with flux_compute stuff below so only 1 call to get_geometry @ face....not sure why this way?!
1432 
1433 
1435  //
1436  // actually compute the dissipative flux
1437  //
1439 
1440  if(splitmaem==0){
1441  MYFUN(flux_compute_general(i, j, k, dir, ptrgeom, CUf, MAC(pr,i,j,k), MACP1A0(pl_ct,dir,i,j,k), MACP1A0(pr_ct,dir,i,j,k), MAC(F,i,j,k), &ctop),"step_ch.c:fluxcalc()", "flux_compute", 1);
1442  }
1443  else{
1444  MYFUN(flux_compute_splitmaem(i, j, k, dir, ptrgeom, CUf, MAC(pr,i,j,k), MACP1A0(pl_ct,dir,i,j,k), MACP1A0(pr_ct,dir,i,j,k), MAC(F,i,j,k), MAC(FEM,i,j,k), &ctop),"step_ch.c:fluxcalc()", "flux_compute", 1);
1445  }
1446 
1447 
1449  //
1450  // evaluate restriction on timestep
1451  //
1453  // below is old before new grid sectioning
1454  //#if( (DOEVOLVEMETRIC || DOSELFGRAVVSR) && (RESTRICTDTSETTINGINSIDEHORIZON==2))
1455  // // avoid limiting dt if inside horizon
1456  // // GODMARK: can only do this if boundary condition does not drive solution's dt behavior
1457  // if(WITHINENERREGION(enerposreg[OUTSIDEHORIZONENERREGION],i,j,k))
1458  //#endif
1459 
1460 
1462  // set dt for this cell in this direction
1463  dtij = cour * dx[dir] / ctop;
1464 
1465 
1467  //
1468  // save minimum dt
1469  //
1471  if(PERCELLDT==0){
1472 
1473  // only set timestep if in computational domain or just +-1 cell beyond. Don't go further since end up not really using that flux or rely on the stability of fluxes beyond that point.
1474  // Need +-1 in case flow is driven by injection boundary conditions rather than what's on grid
1475  if(WITHINACTIVESECTIONEXPAND1(i,j,k)){
1476 #pragma omp critical
1477  {// *ndt and waveglobaldt's have to have blocked write access for OpenMP
1478  if (dtij < *ndt){
1479  *ndt = dtij;
1480  // below are global so can report when other dt's are reported in advance.c
1481  waveglobaldti[dir]=i;
1482  waveglobaldtj[dir]=j;
1483  waveglobaldtk[dir]=k;
1484  }
1485  }// end critical region
1486  }// end if within dt-setting section
1487  }
1488  else{
1489  GLOBALMACP0A1(dtijk,i,j,k,dir) = dtij;
1490  }
1491 
1492 
1493 
1494  }// end if doing computing using both left+right states (required also for ctop to exist)
1495 
1496 
1497  }// end FLUX LOOP
1498  }// end parallel region
1499 
1500 
1501 
1502 
1503 
1504  return (0);
1505 }
1506 
1507 
1508 
1509 
1510 
1511 
1512 
1513 
1514 
1515 
1518 int interpolate_prim_cent2face(int stage, int realisinterp, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], int dir, SFTYPE time, int is, int ie, int js, int je, int ks, int ke, int idel, int jdel, int kdel, int face, FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop)
1519 {
1520  void slope_lim_cent2face(int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*primreal)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop);
1521  int getplpr(int dir, SFTYPE time, int idel, int jdel, int kdel, int i, int j, int k, struct of_geom *geom, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE *p2interp_l, FTYPE *p2interp_r, FTYPE *p_l, FTYPE *p_r);
1522  void compute_and_store_fluxstate(int dimen, int isleftright, int i, int j, int k, struct of_geom *geom, FTYPE *pr);
1523  FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP];
1524  int nprlocalstart,nprlocalend;
1525  int nprlocallist[MAXNPR];
1526  int realis,realie,realjs,realje,realks,realke;
1527  int dointerpolation;
1528 
1529 
1530 
1531 
1532 
1533  // if inside this function, then doing interpolation
1534  dointerpolation=1;
1535 
1536 
1538  //
1539  // setup interpolation so avoids staggered field for field along "dir" direction
1540  // avoid magnetic field interpolation along "dir" direction using slope_lim() that is for cent->edges only
1541  // inside getplpr() staggered field is assigned to final p_l p_r before flux is computed
1542  //
1544  if(FLUXB==FLUXCTSTAG){
1545  int pl,pl2;
1547  //
1548  // save choice for interpolations
1549  nprlocalstart=npr2interpstart;
1550  nprlocalend=npr2interpend;
1551  PMAXNPRLOOP(pl) nprlocallist[pl]=npr2interplist[pl];
1552 
1553 
1554 #pragma omp parallel private(pl,pl2)
1555  { // must set npr2interp stuff inside parallel region since threadprivate
1556  // choice for range of PLOOPINTERP
1557  // check if wanted to interpolate B along dir, and if so remove
1558  for(pl=npr2interpstart;pl<=npr2interpend;pl++){
1559  if(npr2interplist[pl]==B1+dir-1){
1560  for(pl2=pl+1;pl2<=npr2interpend;pl2++) npr2interplist[pl2-1]=npr2interplist[pl2]; // moving upper to lower index
1561  npr2interpend--; // lost field along dir, so one less thing to do
1562  break;
1563  }
1564  }
1565  }
1566 
1567  }
1568 
1569 
1570 
1572  //
1573  // rescale before interpolation
1574  //
1576 #if(RESCALEINTERP)
1577  // assume if DOEXTRAINTERP==1, then must get here
1578  p2interp=GLOBALPOINT(prc); // it's different
1579  rescale_calc_full(dir,pr,p2interp);
1580 #else
1581  p2interp=pr; // it's itself
1582 #endif
1583 
1584 
1585 
1586 
1587 
1588 
1590  //
1591  // evaluate slopes (dq) or get pleft/pright of (possibly rescaled) primitive variables
1592  // c2e reconstruction: p2interp -> pleft & pright (indexed by grid cell #) -- atch comment
1593  //
1595  slope_lim_cent2face(dointerpolation,realisinterp,dir,idel,jdel,kdel,pr,p2interp,dq,GLOBALPOINT(pleft),GLOBALPOINT(pright),cent2faceloop);
1596 
1597 
1598  // override normal fluxloop
1599  if(extrazones4emf){
1600  // don't really need fluxes in this domain, but do need interpolated face values to be transferred from pleft/pright to pl_ct pr_ct
1601  realis=emfUconsloop[FIS]-SHIFT1;
1602  realie=emfUconsloop[FIE]+SHIFT1;
1603  realjs=emfUconsloop[FJS]-SHIFT2;
1604  realje=emfUconsloop[FJE]+SHIFT2;
1605  realks=emfUconsloop[FKS]-SHIFT3;
1606  realke=emfUconsloop[FKE]+SHIFT3;
1607  }
1608  else{ // otherwise normal
1609  realis=is;
1610  realie=ie;
1611  realjs=js;
1612  realje=je;
1613  realks=ks;
1614  realke=ke;
1615  }
1616 
1617 
1618 
1620  //
1621  // flux loop : Extra "expand" zone for the purpose of averaging flux to get emf at corner. Only used by field components, see flux_ct().
1622  // This loop is over interfaces where fluxes are evaluated -- atch
1623  //
1625 
1626  //#if((SIMULBCCALC==2)&&(TYPE2==1))
1627  // COMPFZLOOP(realis,realjs,realks)
1628  //#else
1629  //#endif
1631 
1632 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOM // storage of state requires full copyin()
1633  {
1634  FTYPE p_l[NPR2INTERP], p_r[NPR2INTERP];
1635  FTYPE pstore_l[NPR2INTERP],pstore_r[NPR2INTERP];
1636  FTYPE *p2interp_l,*p2interp_r;
1637  int pl,pliter;
1638  int i,j,k;
1639  struct of_geom geomdontuse;
1640  struct of_geom *ptrgeom=&geomdontuse;
1641  int computewithleft,computewithright;
1642 
1643  OPENMP3DLOOPVARSDEFINE; OPENMP3DLOOPSETUP( realis, realie, realjs, realje, realks, realke );
1644 
1645  // Setup rescale pointer reference
1646 #if(RESCALEINTERP)
1647  p2interp_l=pstore_l; // then need separate storage
1648  p2interp_r=pstore_r;
1649 #else
1650  p2interp_l=p_l; // p2interp_? is final p_?
1651  p2interp_r=p_r;
1652 #endif
1653 
1654 
1655 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1657  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1658 
1659 
1661  //
1662  // get the geometry for the flux face
1663  //
1665  get_geometry(i, j, k, face, ptrgeom);
1666 
1667 
1669  //
1670  // use p2interp,dq,pleft,pright to get p_l and p_r
1671  //
1673 
1674  MYFUN(getplpr(dir,time,idel,jdel,kdel,i,j,k,ptrgeom,pr,pstag,p2interp,dq,GLOBALPOINT(pleft),GLOBALPOINT(pright),p2interp_l,p2interp_r,p_l,p_r),"flux.c:fluxcalc_standard()", "getplpr", 1);
1675  if(SPLITNPR || FLUXB==FLUXCTSTAG){
1676  // then means there is going to be a second pass, so store into memory
1677  PINTERPLOOP(pliter,pl){
1678  MACP1A1(pl_ct,dir,i,j,k,pl)=p_l[pl];
1679  MACP1A1(pr_ct,dir,i,j,k,pl)=p_r[pl];
1680  }
1681  }
1682  if(FLUXB==FLUXCTSTAG){
1683  // then also get B in dir direction not included in interpolation in slope_lim() above but included in getplpr() from pstagscratch[]
1684  pl = B1+dir-1;
1685  MACP1A1(pl_ct,dir,i,j,k,pl)=p_l[pl];
1686  MACP1A1(pr_ct,dir,i,j,k,pl)=p_r[pl];
1687  }
1688 
1689 
1690  // determine whether should compute things using left/right states
1691  // note that should only do non-left non-right state stuff (like computing dt) if both left+right states being done
1692  leftrightcompute(i, j, k, dir, is, ie, js, je, ks, ke, &computewithleft, &computewithright);
1693 
1694 
1696  //
1697  // Compute and Store (globally) the get_state() data for the flux positions to avoid computing later
1698  //
1700 #if(STOREFLUXSTATE)
1701  if(computewithleft) compute_and_store_fluxstate(dir, ISLEFT, i, j, k, ptrgeom, p_l);
1702  if(computewithright) compute_and_store_fluxstate(dir, ISRIGHT, i, j, k, ptrgeom, p_r);
1703  // now flux_compute() and other flux-position-related things will obtain get_state() data for p_l and p_r from global arrays
1704 #endif
1705 
1706 
1707 
1708 
1709  }// end COMPZLOOP
1710  }// end parallel region
1711 
1712 
1713 
1714 
1715 
1716 
1717 
1718 #if(0)
1719  // DEBUG: (didn't matter)
1720  bound_prim(STAGEM1,pl_ct[dir]);
1721  bound_prim(STAGEM1,pr_ct[dir]);
1722 #endif
1723 
1724 
1725 
1726 
1727  if(FLUXB==FLUXCTSTAG){
1728  int pl,pliter;
1730  //
1731  // restore choice for interpolations
1732 #pragma omp parallel private(pl)
1733  { // must set npr2interp stuff inside parallel region since threadprivate
1734  npr2interpstart=nprlocalstart;
1735  npr2interpend=nprlocalend;
1736  PMAXNPRLOOP(pl) npr2interplist[pl]=nprlocallist[pl];
1737  }
1738  }
1739 
1740 
1741  return(0);
1742 
1743 }
1744 
1745 
1746 
1750 void compute_and_store_fluxstate_assign(int dimeninput, int dimenoutput, int isleftrightinput, int isleftrightoutput, int i, int j, int k)
1751 {
1752 
1753  // copy entire structure
1754  GLOBALMACP1A1(fluxstate,dimenoutput,i,j,k,isleftrightoutput)=GLOBALMACP1A1(fluxstate,dimeninput,i,j,k,isleftrightinput);
1755 
1756 }
1757 
1760 void compute_and_store_fluxstate(int dimen, int isleftright, int i, int j, int k, struct of_geom *geom, FTYPE *pr)
1761 {
1762  int pureget_stateforfluxcalc(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1763 
1764  // get state
1765  pureget_stateforfluxcalc(pr,geom,&GLOBALMACP1A1(fluxstate,dimen,i,j,k,isleftright));
1766 
1767 }
1768 
1769 
1770 
1772 void compute_and_store_fluxstatecent(FTYPE (*pr)[NSTORE2][NSTORE3][NPR])
1773 {
1774  int pureget_stateforfluxcalcorsource(FTYPE *pr, struct of_geom *ptrgeom, struct of_state *q);
1775  int is,ie,js,je,ks,ke,di,dj,dk;
1776  // FTYPE (*shocktemparray)[NSTORE2][NSTORE3][NPR];
1778  int startorderi,endorderi;
1779  extern FTYPE Ficalc(int dir, FTYPE *V, FTYPE *P);
1780  extern FTYPE Divcalc(int dir, FTYPE Fi, FTYPE *V, FTYPE *P);
1781 
1782 
1783 
1784  const int Nvec[NDIM]={0,N1,N2,N3};
1785  const int NxNOT1[NDIM]={0,N1NOT1,N2NOT1,N3NOT1};
1786 
1787  // setup temporary space
1788  shocktemparray = GLOBALPOINT(emf);
1789 
1790  // define +-1 in every direction loop range
1791  int loc=CENT;
1792  int continuous=0;
1793  set_interppoint_loop_ranges_3Dextended(ENOINTERPTYPE, loc, continuous, &is, &ie, &js, &je, &ks, &ke, &di, &dj, &dk);
1794 
1795 
1796 #if(STOREFLUXSTATE||STORESHOCKINDICATOR)
1797 
1799  //
1800  // loop over all i,j,k
1801  //
1803  // COMPZSLOOP(is,ie,js,je,ks,ke){
1804  // COMPFULLLOOP{ // NOTE: Using COMPFULLLOOP now since using this CENT for many things, including global wave speed calculation that currently uses COMPFULLOOP
1805 #pragma omp parallel OPENMPGLOBALPRIVATEFORSTATEANDGEOM // requires full copyin()
1806  {
1807  int i,j,k;
1808  struct of_geom geomdontuse;
1809  struct of_geom *ptrgeom=&geomdontuse;
1810  int dir;
1811 
1813 
1814 
1815 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1817  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1818 
1819 
1820 
1821  // set geometry for centered zone to be updated
1822  get_geometry(i, j, k, CENT, ptrgeom);
1823 
1824  // get state
1825  pureget_stateforfluxcalcorsource(MAC(pr,i,j,k),ptrgeom,&GLOBALMAC(fluxstatecent,i,j,k));
1826 
1827  // FTYPE flux[NDIM];
1828  // mhd_calc(MAC(pr,i,j,k),TT,ptrgeom,&GLOBALMAC(fluxstatecent,i,j,k),flux,NULL);
1829 
1830 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE) // KORAL
1831  // get true directional energy flux instead of fake flux
1832  // FTYPE fluxrad[NDIM];
1833  // mhd_calc_rad(MAC(pr,i,j,k),TT,ptrgeom,&GLOBALMAC(fluxstatecent,i,j,k),fluxrad,NULL);
1834 #endif
1835 
1836 
1837 #if(STORESHOCKINDICATOR)
1838  // see more details in interpline.c:get_V_and_P()
1839 
1840 
1841  DIMENLOOP(dir){
1842  if(NxNOT1[dir]){
1843 #if(VLINEWITHGDETRHO==0)
1844  MACP1A0(shocktemparray,SHOCKPLSTOREVEL1+dir-1,i,j,k)=MACP0A1(pr,i,j,k,UU+dir);
1845 #else
1846  //MACP1A0(shocktemparray,SHOCKPLSTOREVEL1+dir-1,i,j,k)=(ptrgeom->gdet)*MACP0A1(pr,i,j,k,RHO)*(GLOBALMAC(fluxstatecent,i,j,k).ucon[dir]);
1847  MACP1A0(shocktemparray,SHOCKPLSTOREVEL1+dir-1,i,j,k)=(ptrgeom->gdet)*(GLOBALMAC(fluxstatecent,i,j,k).ucon[dir]);
1848  // MACP1A0(shocktemparray,SHOCKPLSTOREVEL1+dir-1,i,j,k) = (ptrgeom->gdet)*(-flux[dir]);
1849 #endif
1850 
1851 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE) // KORAL
1852 #if(VLINEWITHGDETRHO==0)
1853  MACP1A0(shocktemparray,SHOCKRADPLSTOREVEL1+dir-1,i,j,k) = MACP0A1(pr,i,j,k,URAD0+dir);
1854 #else
1855  //MACP1A0(shocktemparray,SHOCKRADPLSTOREVEL1+dir-1,i,j,k) = (ptrgeom->gdet)*MACP0A1(pr,i,j,k,URAD0)*(GLOBALMAC(fluxstatecent,i,j,k).uradcon[dir]);
1856  MACP1A0(shocktemparray,SHOCKRADPLSTOREVEL1+dir-1,i,j,k) = (ptrgeom->gdet)*(GLOBALMAC(fluxstatecent,i,j,k).uradcon[dir]);
1857  //MACP1A0(shocktemparray,SHOCKRADPLSTOREVEL1+dir-1,i,j,k) = (ptrgeom->gdet)*(-fluxrad[dir]);
1858 #endif
1859 #endif
1860  }
1861  }
1862 
1863 
1864  // get total MHD pressure
1865  FTYPE pmhd=GLOBALMAC(fluxstatecent,i,j,k).pressure + 0.5*GLOBALMAC(fluxstatecent,i,j,k).bsq;
1866  MACP1A0(shocktemparray,SHOCKPLSTOREPTOT,i,j,k)=pmhd;
1867 
1868 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE) // KORAL
1869  FTYPE prad=(4.0/3.0-1.0)*MACP0A1(pr,i,j,k,PRAD0); // KORALNOTE: recall pressure just along diagonal and no velocity in R^\mu_\nu
1870  MACP1A0(shocktemparray,SHOCKRADPLSTOREPTOT,i,j,k) = prad;
1871 
1872  // add radiation pressure to total pressure if optically thick
1873  FTYPE tautot[NDIM],tautotmax;
1874  // &GLOBALMAC(fluxstatecent,i,j,k)
1875  calc_tautot(&MACP0A1(pr,i,j,k,0), ptrgeom, NULL, tautot, &tautotmax); // high accuracy not required
1876 
1877  MACP1A0(shocktemparray,SHOCKPLSTOREPTOT,i,j,k) += MIN(tautotmax/TAUTOTMAXSWITCH,1.0)*prad;
1878  MACP1A0(shocktemparray,SHOCKRADPLSTOREPTOT,i,j,k) += MIN(tautotmax/TAUTOTMAXSWITCH,1.0)*pmhd;
1879 #endif
1880 
1881 #endif // end if STORESHOCKINDICATOR
1882 
1883 
1884 
1885 #if(STOREFLUXSTATE)
1886 
1887  // if dimension doesn't exist, then copy over fluxstatecent to fluxstate[dimen][ISLEFT,ISRIGHT]
1888  // If doing staggered field method, then also assumes left,right stored like pl_ct and pr_ct are stored
1889  // note we are copying entire structure here
1890 
1891  DIMENLOOP(dir){
1892 
1893  if(NxNOT1[dir]==0 || FIELDSTAGMEM){
1894  // if dimension doesn't exist, then copy over fluxstatecent to fluxstate[dimen][ISLEFT,ISRIGHT]
1895  GLOBALMACP1A1(fluxstate,dir,i,j,k,ISLEFT)=GLOBALMAC(fluxstatecent,i,j,k);
1896  GLOBALMACP1A1(fluxstate,dir,i,j,k,ISRIGHT)=GLOBALMAC(fluxstatecent,i,j,k);
1897  }
1898  }
1899 
1900 #endif// end if STOREFLUXSTATE
1901 
1902  }// end 3D loop
1903  }// end parallel region
1904 
1905 #endif// end if STOREFLUXSTATE|| STORESHOCKINDICATOR
1906 
1907 
1908 
1909 
1910 
1911 
1912  {// begin block
1913 
1914 
1915 
1916 #if(STORESHOCKINDICATOR)
1917  // OPTMARK: Consider storing temporary velvec aligned with extraction direction (dir) . Although ptot scalar has no preferred choice and final pr should have standard choice.
1918  // Ficalc() requires vel and p exist +-2 beyond where shock indicator is computed.
1919  // Assume shock indicator required at largest possible domain, which is then 2-inwards from outer boundaries only in each direction.
1920  // shockindicatorarray[] computed here is used in interpline.c when calling get_1d_line_shockarray() to get shockindicator[]
1921 
1922 #if(MAXBND<4)
1923  dualfprintf(fail_file,"MAXBND should be 4 for shockindicator???\n");
1924  myexit(8465684);
1925 #endif
1926 
1927  startorderi = - (7)/2; // order=7 fixed for shock detector
1928  endorderi = - startorderi;
1929 
1930 
1931 
1932 #pragma omp parallel
1933  {
1934  int dir;
1935  int imod,jmod,kmod;
1936  int gotgeometry=0;
1937  int i,j,k,l;
1938  int pl;
1940  // FTYPE *primptr[MAXNPR]; // number of pointers
1941  FTYPE *velptr,*ptotptr;
1942  // FTYPE a_primstencil[MAXNPR][MAXSPACEORDER];
1943  FTYPE a_velstencil[MAXSPACEORDER],a_ptotstencil[MAXSPACEORDER]; // Shouldn't need anymore than 10
1944 
1945 
1946  // shift pointer
1947  // PALLREALLOOP(pl){
1948  // primptr[pl] = a_primstencil[pl] - startorderi;
1949  // }
1950  velptr = a_velstencil - startorderi;
1951  ptotptr = a_ptotstencil - startorderi;
1952 
1953 
1954  // if(dir==1) OPENMP3DLOOPSETUPFULLINOUT2DIR1;
1955  // if(dir==2) OPENMP3DLOOPSETUPFULLINOUT2DIR2;
1956  // if(dir==3) OPENMP3DLOOPSETUPFULLINOUT2DIR3;
1958 #pragma omp for schedule(OPENMPSCHEDULE(),OPENMPCHUNKSIZE(blocksize))
1960  OPENMP3DLOOPBLOCK2IJK(i,j,k);
1961 
1962  FTYPE radshock={0},mhdshock={0}; // KORALTODO: Not used yet, but can be roughly used to pull-over multiple dimensions for shock indicator
1963 
1964  DIMENLOOP(dir){
1965  if(NxNOT1[dir]){
1966 
1967 
1968  // extract stencil of data for Ficalc()
1969  for(l=startorderi;l<=endorderi;l++){
1970  imod=i+(dir==1)*l;
1971  jmod=j+(dir==2)*l;
1972  kmod=k+(dir==3)*l;
1973 
1974  imod=MAX(-N1BND,imod);
1975  imod=MIN(N1-1+N1BND,imod);
1976 
1977  jmod=MAX(-N2BND,jmod);
1978  jmod=MIN(N2-1+N2BND,jmod);
1979 
1980  kmod=MAX(-N3BND,kmod);
1981  kmod=MIN(N3-1+N3BND,kmod);
1982 
1983 
1984  // PALLREALLOOP(pl) primptr[pl][l] = MACP0A1(pr,imod,jmod,kmod,pl);
1985  velptr[l] = MACP1A0(shocktemparray,SHOCKPLSTOREVEL1+dir-1,imod,jmod,kmod);
1986  ptotptr[l] = MACP1A0(shocktemparray,SHOCKPLSTOREPTOT,imod,jmod,kmod);
1987  }
1988 
1989  FTYPE Fi;
1990  // GLOBALMACP0A1(shockindicatorarray,i,j,k,SHOCKPLDIR1+dir-1)=Ficalc(dir,&velptr[0],&ptotptr[0],&primptr[0]);
1991  Fi=Ficalc(dir,&velptr[0],&ptotptr[0]);
1992  // Fi=1.0;
1993  if(NSPECIAL>=1&&0 && DODISSMEASURE){
1994  FTYPE dissit=fabs(GLOBALMACP0A1(dissmeasurearray,i,j,k,1));
1995  dissit = MAX(0.0,MIN(1,2*(dissit-0.3)));
1996  Fi=MIN(1.0,MAX(Fi,dissit));
1997  }
1998  if(steppart>0) Fi=MAX(Fi,GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k));
1999  GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k)=Fi;
2000 
2001  // DEBUG
2002  if(DODISSMEASURE){
2003  GLOBALMACP0A1(dissmeasurearray,i,j,k,NSPECIAL+1+dir-1)=GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k);
2004  }
2005  // if(i==399){
2006  // for(l=startorderi;l<=endorderi;l++){
2007  // dualfprintf(fail_file,"GAS: l=%d vel=%g ptot=%g\n",l,velptr[l],ptotptr[l]);
2008  // }
2009  // }
2010 
2011 
2013  GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k)=Divcalc(dir,Fi,&velptr[0],&ptotptr[0]);
2014  }
2015 
2017  // extract stencil of data for Ficalc()
2018  for(l=startorderi;l<=endorderi;l++){
2019  imod=i+(dir==1)*l;
2020  jmod=j+(dir==2)*l;
2021  kmod=k+(dir==3)*l;
2022 
2023  imod=MAX(-N1BND,imod);
2024  imod=MIN(N1-1+N1BND,imod);
2025 
2026  jmod=MAX(-N2BND,jmod);
2027  jmod=MIN(N2-1+N2BND,jmod);
2028 
2029  kmod=MAX(-N3BND,kmod);
2030  kmod=MIN(N3-1+N3BND,kmod);
2031 
2032  // PALLREALLOOP(pl) primptr[pl][l] = MACP0A1(pr,imod,jmod,kmod,pl);
2033  velptr[l] = MACP1A0(shocktemparray,SHOCKRADPLSTOREVEL1+dir-1,imod,jmod,kmod);
2034  ptotptr[l] = MACP1A0(shocktemparray,SHOCKRADPLSTOREPTOT,imod,jmod,kmod);
2035  }
2036 
2037  // GLOBALMACP0A1(shockindicatorarray,i,j,k,SHOCKRADPLDIR1+dir-1)=Ficalc(dir,&velptr[0],&ptotptr[0],&primptr[0]);
2038  FTYPE Firad;
2039  Firad=Ficalc(dir,&velptr[0],&ptotptr[0]);
2040  // Firad*=2.0;
2041  // Firad=MIN(1.0,Firad);
2042  if(NSPECIAL>=6&&0 && DODISSMEASURE){
2043  FTYPE dissit=fabs(GLOBALMACP0A1(dissmeasurearray,i,j,k,5));
2044  dissit = MAX(0.0,MIN(1,2*(dissit-0.3)));
2045  Firad=MIN(1.0,MAX(Firad,dissit));
2046  }
2047  if(steppart>0) Firad=MAX(Firad,GLOBALMACP1A0(shockindicatorarray,SHOCKRADPLDIR1+dir-1,i,j,k));
2048  GLOBALMACP1A0(shockindicatorarray,SHOCKRADPLDIR1+dir-1,i,j,k)=Firad;
2049 
2050  //DEBUG
2051  // dualfprintf(fail_file,"nstep=%ld steppart=%d i=%d dir=%d Fi=%g Firad=%g\n",nstep,steppart,i,dir,Fi,Firad);
2052  // if(i==399){
2053  // for(l=startorderi;l<=endorderi;l++){
2054  // dualfprintf(fail_file,"RAD: l=%d vel=%g ptot=%g\n",l,velptr[l],ptotptr[l]);
2055  // }
2056  // }
2057 
2058  // DEBUG
2059  if(DODISSMEASURE){
2060  GLOBALMACP0A1(dissmeasurearray,i,j,k,NSPECIAL+1+3+dir-1)=GLOBALMACP1A0(shockindicatorarray,SHOCKRADPLDIR1+dir-1,i,j,k);
2061  }
2062 
2063 
2065  GLOBALMACP1A0(shockindicatorarray,DIVRADPLDIR1+dir-1,i,j,k)=Divcalc(dir,Firad,&velptr[0],&ptotptr[0]);
2066  }
2067  }// end if doing radiation
2068  }// end if doing dir
2069  }//end over dir loop
2070 
2071  // set geometry for centered zone to be updated
2072  struct of_geom geomdontuse;
2073  struct of_geom *ptrgeom=&geomdontuse;
2074 #if(RADSHOCKFLAT&&EOMRADTYPE!=EOMRADNONE) // KORAL
2075  get_geometry(i, j, k, CENT, ptrgeom);
2076  gotgeometry=1;
2077 
2078  // use maximum shock indicator if optically thick
2079  // KORALTODO: using tau here, but tau is only over a cell. If resolution changes, different tau, yet physics is the same. How to manage?
2080  // KORALNOTE: Need this because radiation can be escaping from shock, so radiation itself is not converging, while still sufficient for MHD shock conditions.
2081  FTYPE tautot[NDIM],tautotmax;
2082  // &GLOBALMAC(fluxstatecent,i,j,k)
2083  calc_tautot(&MACP0A1(pr,i,j,k,0), ptrgeom, NULL, tautot, &tautotmax); // high accuracy not required
2084 
2085  DIMENLOOP(dir){
2086  if(NxNOT1[dir]){
2087  FTYPE Firad=GLOBALMACP1A0(shockindicatorarray,SHOCKRADPLDIR1+dir-1,i,j,k);
2088  FTYPE Fi=GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k);
2089  FTYPE Fiswitch =MIN(tautotmax/TAUTOTMAXSWITCH,1.0);
2090 
2091  GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k) = Fiswitch*MIN(1.0,MAX(Firad,Fi)) + (1.0-Fiswitch)*Fi;
2092  GLOBALMACP1A0(shockindicatorarray,SHOCKRADPLDIR1+dir-1,i,j,k) = Fiswitch*MIN(1.0,MAX(Firad,Fi)) + (1.0-Fiswitch)*Firad;
2093 
2094 
2095 
2097  // don't consider radiation divergence, and certainly not as if shock indiator value.
2098  // GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k) = MAX(MIN(tautotmax/TAUTOTMAXSWITCH,1.0)*GLOBALMACP1A0(shockindicatorarray,DIVRADPLDIR1+dir-1,i,j,k),GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k));
2099  // GLOBALMACP1A0(shockindicatorarray,DIVRADPLDIR1+dir-1,i,j,k) = MAX(MIN(tautotmax/TAUTOTMAXSWITCH,1.0)*GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k),GLOBALMACP1A0(shockindicatorarray,DIVRADPLDIR1+dir-1,i,j,k));
2100  }
2101  }
2102  }
2103 #endif
2104 
2105 
2107  //
2108  // compute best indication that entropy equation should be used based upon smoothness of flow
2109  //
2111 
2113 
2114  // set geometry for centered zone to be updated
2115  if(gotgeometry==0) get_geometry(i, j, k, CENT, ptrgeom);
2116 
2117  // first see which divergence is largest in absolute terms accounting for dimensions
2118  FTYPE divcond=-1.0,absdivcond=0.0; // 0.0 here is crucial as reference for divergent flow
2119  FTYPE divcondtest[NDIM],absdivcondtest;
2120  int largestdir=-1;
2121  DIMENLOOP(dir){
2122  if(NxNOT1[dir]){
2123  if(VLINEWITHGDETRHO==0){
2124  divcondtest[dir]=GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k)/(sqrt(fabs(ptrgeom->gcon[GIND(dir,dir)])));
2125  }
2126  else{
2127  divcondtest[dir]=GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k)/(sqrt(fabs(ptrgeom->gcon[GIND(dir,dir)]))*ptrgeom->gdet);
2128  }
2129  absdivcondtest=fabs(divcondtest[dir]);
2130  if(absdivcondtest>absdivcond){
2131  largestdir=dir;
2132  absdivcond=absdivcondtest;
2133  divcond=divcondtest[dir];
2134  }
2135  }
2136  }
2137  // ensure largest divergence dominates
2138  DIMENLOOP(dir){
2139  if(NxNOT1[dir]){
2140 #define MAXSHOCK (0.1)
2141 #define FACTORBIGDIV (10.0)
2142  // only consider fluid, since if optically thick already accounted for radiation in this indicator
2143  if(GLOBALMACP1A0(shockindicatorarray,SHOCKPLDIR1+dir-1,i,j,k)>MAXSHOCK){
2144  divcond=-BIG;
2145  }
2146  // check that divergence is some factor more than convergence in any other direction
2147  if(dir!=largestdir && fabs(divcond)<FACTORBIGDIV*fabs(divcondtest[dir]) && divcondtest[dir]<0.0){
2148  divcond=-BIG;
2149  }
2150  }
2151  }
2152  // divcond now holds divergence condition for largest divergent part of flow. Replace all dimensions with this uni-dimensional condition
2153  DIMENLOOP(dir){
2154  if(NxNOT1[dir]){
2155  GLOBALMACP1A0(shockindicatorarray,DIVPLDIR1+dir-1,i,j,k)=divcond;
2156  }
2157  }
2158  }// end if(DIVERGENCEMETHOD==DIVMETHODPREFLUX)
2159 
2160  }// end 3D loop
2161  }// end parallel region
2162 
2163 
2164 
2165 
2166 
2167 
2168 
2169  // if want to use contact steepener methods, then store that too.
2170  // if(CONTACTINDICATOR){
2172  //
2173  // 1D GET CONTACT INDICATOR
2174  //
2176  //use primitive values that correspond to the quantities being interpolated
2177  // }
2178 
2179 
2180 
2181  // GODMARK: At end, could combine into multi-dimensional shock indicator. But should have measure to neglect other minor dimensions where (e.g.) velocity or pressure jumps not important)
2182 
2183 
2184 #endif // end if STORESHOCKINDICATOR
2185  }// end block
2186 
2187 
2188 
2189 }
2190 
2191 
2192 
2193 
2194 
2195 
2196 
2197 
2199 int getplpr(int dir, SFTYPE time, int idel, int jdel, int kdel, int i, int j, int k, struct of_geom *ptrgeom, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE *p2interp_l, FTYPE *p2interp_r, FTYPE *p_l, FTYPE *p_r)
2200 {
2201  void getp2interplr(int dir, int idel, int jdel, int kdel, int i, int j, int k, FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE *p2interp_l, FTYPE *p2interp_r);
2202  int check_plpr(int dir, int i, int j, int k, int idel, int jdel, int kdel, struct of_geom *geom, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE *p_l, FTYPE *p_r);
2203  int pl,pliter;
2204 
2205 
2206 
2208  //
2209  // interpolate primitive using slope (dq) or directly from pleft and pright
2210  // For FV: p_left, p_right (indexed by grid cell #) -> p2interp_l, p2interp_r (indexed by interface #) -- atch comment
2211  //
2212  // always do since p2interp is good and dq/pleft/pright should have stored quantities or just-computed quantities
2214  getp2interplr(dir,idel,jdel,kdel,i,j,k,p2interp,dq,pleft,pright,p2interp_l,p2interp_r);
2215 
2216 
2217 
2219  //
2220  // after interpolation, unrescale from p2interp to normal primitive
2221  // p2interp_? is p_? if not rescaling, so no need to assign p2interp_? to p_? if not rescaling
2222  //
2224  if(RESCALEINTERP && npr2interpstart<=npr2interpend){
2225  // only do if some interpolation done (consistent with no rescale() done in fluxcalc_standard() above
2226  // setup plausible p_l/p_r in case used for some reason (e.g. inversion starting guess)
2227  // this is sufficient for utoprim_1D...a better guess does no better (see interpU code)
2228  PINTERPLOOP(pliter,pl){
2229  p_l[pl]=MACP0A1(pr,i,j,k,pl);
2230  p_r[pl]=MACP0A1(pr,i,j,k,pl);
2231  }
2232  rescale(UNRESCALE,dir,p_l,ptrgeom,p2interp_l);
2233  rescale(UNRESCALE,dir,p_r,ptrgeom,p2interp_r);
2234  }
2235 
2236 
2237 
2238 
2240  //
2241  // Must preserve divb in 1D Riemann problem, so B^{dir} must be continuous
2242  //
2243  // GODMARK: Should really interpolate SUCH THAT this is automatically satisfied?
2244  // Yes, should use larger stencil and interpolate such that constant. Essentially choose
2245  // large stencil and effectively choosing which points we trust (not necessarily local points)
2246  //
2247  // GODMARK: This does not enforce E_\perp to be continuous for stationary flow!
2248  //
2250 
2251 
2252  if(FLUXB==FLUXCTSTAG){
2253  // exactly correct that there is only 1 value
2254  pl = B1+dir-1;
2255  p_l[pl]=p_r[pl]=MACP0A1(pstag,i,j,k,pl);
2256  }
2257  else{
2258 #if(BDIRCONT)
2259  // should really interpolate such that p_l=p_r
2260  pl = B1+dir-1;
2261  p_l[pl]=p_r[pl]=0.5*(p_l[pl]+p_r[pl]);
2262 #endif
2263  }
2264 
2265 
2266 #if(BOUNDPLPR)
2267  set_plpr(dir,time,i,j,k,pr,p_l,p_r);
2268 #endif
2269 
2271  //
2272  // correct interpolated quantities
2273  // no fixup accounting for these intermediate quantities
2274  //
2276  MYFUN(check_plpr(dir, i, j, k, idel, jdel, kdel, ptrgeom, pr, p_l, p_r),"step_ch.c:fluxcalc()", "check_plpr()", 1);
2277 
2278 
2279  return(0);
2280 
2281 }
2282 
2283 
2284 
2285 
2286 
2288 int check_plpr(int dir, int i, int j, int k, int idel, int jdel, int kdel, struct of_geom *geom, FTYPE (*pr)[NSTORE2][NSTORE3][NPR], FTYPE *p_l, FTYPE *p_r)
2289 {
2290  int pl,pliter;
2291 
2292 #if(EVOLVECHECKS)
2293 #if(WHICHVEL==VEL4)
2294 #if(ZEROOUTFLOWFLUX==1)
2295  inflow_check_4vel(dir,p_l,NULL,-1);
2296  inflow_check_4vel(dir,p_r,NULL,geom,-1);
2297 #endif
2298 #elif(WHICHVEL==VEL3)
2299 #if(ZEROOUTFLOWFLUX==1)
2300  inflow_check_3vel(dir,p_l,NULL,geom,-1);
2301  inflow_check_3vel(dir,p_r,NULL,geom,-1);
2302 #endif
2303 #if(JONCHECKS2)
2304  // must verify if this p makes sense (u^t sense)
2305  MYFUN(check_pr(p_l,MAC(pr,i-idel,j-jdel,k-kdel),NULL,geom,1,-1.0),"flux.c:check_plpr()", "check_pr()", 1);
2306 
2307  MYFUN(check_pr(p_r,MAC(pr,i,j,k),NULL,geom,2,-1),"flux.c:check_plpr()", "check_pr()", 2);
2308 #endif
2309 #elif(WHICHVEL==VELREL4)
2310 #if(ZEROOUTFLOWFLUX==1)
2311  inflow_check_rel4vel(dir,p_l,NULL,geom,-1);
2312  inflow_check_rel4vel(dir,p_r,NULL,geom,-1);
2313 #endif
2314  // need to limit gamma since gamma may be large for interpolated value and would lead to bad fluxes
2315  MYFUN(limit_gamma(0,GAMMAMAX,GAMMAMAXRAD,p_l,NULL,geom,-1),"flux.c:check_plpr()", "limit_gamma()", 1); //jon corr, see email re: SPINT warnings from 4/24/2006 10:54 p.m.
2316  MYFUN(limit_gamma(0,GAMMAMAX,GAMMAMAXRAD,p_r,NULL,geom,-1),"flux.c:check_plpr()", "limit_gamma()", 2); //jon corr
2317 #endif// end if WHICHVEL==VEL4REL
2318 #endif
2319 
2320 
2321 #if(PRODUCTION==0 && MERGEDC2EA2CMETHOD==0)
2322  // NOTE: with merged method use expanded loops that will use bogus data, but done for simplicity. So no nan check possible there -- assume fill bad regions with zeroes
2323  PINTERPLOOP(pliter,pl) if(!isfinite(p_l[pl])){
2324  dualfprintf(fail_file,"nstep=%ld steppart=%d i=%d j=%d k=%d :: p_l is not finite pl=%d p_l=%21.15g\n",nstep,steppart,i,j,k,pl,p_l[pl]);
2325  }
2326  PINTERPLOOP(pliter,pl) if(!isfinite(p_r[pl])){
2327  dualfprintf(fail_file,"nstep=%ld steppart=%d i=%d j=%d k=%d :: p_r is not finite pl=%d p_r=%21.15g\n",nstep,steppart,i,j,k,pl,p_r[pl]);
2328  }
2329 #endif
2330 
2331  // DEBUG:
2332  // dualfprintf(fail_file,"CHECK dir=%d :: i=%d j=%d k=%d\n",dir,i,j,k);
2333 
2334 
2335  return(0);
2336 }
2337 
2338 
2339 
2340 
2341 
2342 
2343 
2361 void getp2interplr(int dir, int idel, int jdel, int kdel, int i, int j, int k, FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE *p2interp_l, FTYPE *p2interp_r)
2362 {
2363  FTYPE Xcent[NDIM],Xleft[NDIM];
2364  FTYPE Vcent[NDIM],Vleft[NDIM];
2365  FTYPE rleft,rcenter,thleft,thcent;
2366  int pl,pliter;
2367  int locallim;
2368  int choose_limiter(int dir, int i, int j, int k, int pl);
2369 
2370 
2372  //
2373  // reshuffle dq's such that reconstruction within active zones does not use the boundary values
2374  //
2376  remapdq( dir, idel, jdel, kdel, i, j, k, p2interp, dq, pleft, pright, p2interp_l, p2interp_r);
2377 
2378 
2380  //
2381  // Do interpolation
2382  //
2384 
2385  if((HORIZONSUPERFAST)&&((lim[dir]<PARA)&&(LIMADJUST==0))&&(dir==1)){
2386  // since this uses dq's to shift, must always have dq's everywhere. Hence LIMADJUST==0 and lim<PARA must be true
2387  bl_coord_ijk_2(im1mac(i), j, k, CENT, Xleft,Vleft);
2388  bl_coord_ijk_2(i, j, k, CENT, Xcent,Vcent);
2389  rleft=Vleft[1];
2390  thleft=Vleft[2];
2391  rcenter=Vcent[1];
2392  thcent=Vcent[2];
2393 
2394  PINTERPLOOP(pliter,pl){
2395  locallim=choose_limiter(dir, i,j,k,pl);
2396  int usedq = usedqarray[locallim];
2397  // get interpolated quantity
2398  if(usedq){
2399  if(rleft>Rhor) p2interp_l[pl] = MACP0A1(p2interp,i - idel,j - jdel,k - kdel,pl) + 0.5 * MACP0A1(dq,i - idel,j - jdel,k - kdel,pl);
2400  else p2interp_l[pl] = MACP0A1(p2interp,i,j,k,pl) - 0.5 * MACP0A1(dq,i,j,k,pl);
2401  if(rcenter>Rhor) p2interp_r[pl] = MACP0A1(p2interp,i,j,k,pl) - 0.5 * MACP0A1(dq,i,j,k,pl);
2402  else p2interp_r[pl] = MACP0A1(p2interp,i+idel,j+jdel,k+kdel,pl) - 1.5 * MACP0A1(dq,i+idel,j+jdel,k+kdel,pl);
2403  }
2404  else{
2405  p2interp_l[pl] = MACP0A1(pright,i-idel,j-jdel,k-kdel,pl);
2406  p2interp_r[pl] = MACP0A1(pleft,i,j,k,pl);
2407  }
2408  } // end PLOOPINTERP
2409  }// if horizonsuperfast
2410  else{
2412  //
2413  // standard routine
2414  //
2416  PINTERPLOOP(pliter,pl){
2417  locallim=choose_limiter(dir, i,j,k,pl);
2418  int usedq = usedqarray[locallim];
2419  // get interpolated quantity
2420  if(usedq){
2421  p2interp_l[pl] = MACP0A1(p2interp,i - idel,j - jdel,k - kdel,pl) + 0.5 * MACP0A1(dq,i - idel,j - jdel,k - kdel,pl);
2422  p2interp_r[pl] = MACP0A1(p2interp,i,j,k,pl) - 0.5 * MACP0A1(dq,i,j,k,pl);
2423  }
2424  else{
2425  //p_l & p_r for the current interface -- atch comment
2426  p2interp_l[pl] = MACP0A1(pright,i-idel,j-jdel,k-kdel,pl);
2427  p2interp_r[pl] = MACP0A1(pleft,i,j,k,pl);
2428  }
2429  }
2430  }
2431 
2432 
2433 
2435  //
2436  // for boundaries where grid cells are avoided: set outer interface primitives at the boundary equal to inner interface primitive at that boundary
2437  // This function is what's used to force primitives on flux surfaces to be chosen as desired by user rather than interpolated by code
2438  // This is useful (required) if want to properly and exactly define surface of an object where (e.g.) perfect conductivity and other specifications are desired.
2439  //
2441  remapplpr( dir, idel, jdel, kdel, i, j, k, p2interp, dq, pleft, pright, p2interp_l, p2interp_r);
2442 
2443 
2444 }
2445 
2446 
2447 
2448 
2449 
2451 int choose_limiter(int dir, int i, int j, int k, int pl)
2452 {
2453 #if(LIMADJUST==LIMITERFIXED)
2454  // TESTMARK
2455  // if(i>=4) return(lim[dir]);
2456  //else return(DONOR);
2457  return(lim[dir]);
2458 #else
2459 
2460 #if(HYDROLIMADJUSTONLY)
2461  if(pl<B1) return(MACP0A1(pflag,i,j,k,FLAGREALLIM));
2462  else return(lim[dir]);
2463 #else
2464  return(MACP0A1(pflag,i,j,k,FLAGREALLIM));
2465 #endif
2466 
2467 #endif
2468 
2469 }
2470 
2471 
2472 
2473 
2474 
2475 
2476 
2477 
2478 
2491 void slope_lim(int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*primreal)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop)
2492 {
2493  int pl,pliter;
2494 
2495 
2496 
2497 
2498  if( LINEINTERPTYPE(lim[dir]) ){ // this overrides lim, but lim must still be set properly
2499  // ENOPRIMITIVE below means primitives instead of conserved quantities
2500  get_loop(INTERPLINETYPE, ENOINTERPTYPE, dir, cent2faceloop);
2501  if(dointerpolation) slope_lim_linetype_c2e(realisinterp, ENOPRIMITIVE, ENOINTERPTYPE, dir, idel, jdel, kdel, primreal, NULL, p2interp, pleft, pright);
2502  }
2503  else{
2504  int loc=CENT;
2505  int continuous=0;
2506  get_loop(INTERPPOINTTYPE, ENOINTERPTYPE, dir, cent2faceloop);
2507  if(dointerpolation){
2508  PINTERPLOOP(pliter,pl){
2509  slope_lim_pointtype(ENOINTERPTYPE, realisinterp, pl, dir, loc, continuous, idel, jdel, kdel, primreal, p2interp, dq, pleft, pright);
2510  }
2511  }
2512  }
2513 
2514 
2515 
2516 }
2517 
2518 
2519 
2533 void slope_lim_cent2face(int dointerpolation, int realisinterp, int dir, int idel, int jdel, int kdel, FTYPE (*primreal)[NSTORE2][NSTORE3][NPR], FTYPE (*p2interp)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*dq)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pleft)[NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pright)[NSTORE2][NSTORE3][NPR2INTERP], struct of_loop *cent2faceloop)
2534 {
2535  int pl,pliter;
2536  int interporflux;
2537 
2538 
2539  if(extrazones4emf){
2540  interporflux=ENOINTERPTYPE4EMF;
2541 
2542  }
2543  else{
2544  interporflux=ENOINTERPTYPE;
2545  }
2546 
2547 
2548 
2549  if( LINEINTERPTYPE(lim[dir]) ){ // this overrides lim, but lim must still be set properly
2550  // ENOPRIMITIVE below means primitives instead of conserved quantities
2551  get_loop(INTERPLINETYPE, interporflux, dir, cent2faceloop);
2552  if(dointerpolation) slope_lim_linetype_c2e(realisinterp, ENOPRIMITIVE, interporflux, dir, idel, jdel, kdel, primreal, NULL, p2interp, pleft, pright);
2553  }
2554  else{
2555  int loc=CENT;
2556  int continuous=0;
2557  get_loop(INTERPPOINTTYPE, interporflux, dir, cent2faceloop);
2558  if(dointerpolation){
2559  PINTERPLOOP(pliter,pl){
2560  slope_lim_pointtype(interporflux, realisinterp, pl, dir, loc, continuous, idel, jdel, kdel, primreal, p2interp, dq, pleft, pright);
2561  }
2562  }
2563  }
2564 
2565 
2566 
2567 }
2568 
2569 
2570 
2571 
2572 
2573 
2574 
2575 
2576 
2577 
2578 // local corresponding value to global STOREWAVESPEEDS
2579 #define STOREWAVESPEEDMETHOD 1
2580 
2584 //DEBUGREPLACEFUNNAME//int fluxcalc
2585 int fluxcalc_donor
2586 (int stage,
2587  FTYPE (*pr)[NSTORE2][NSTORE3][NPR],
2588  FTYPE (*pstag)[NSTORE2][NSTORE3][NPR],
2589  FTYPE (*pl_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP], FTYPE (*pr_ct)[NSTORE1][NSTORE2][NSTORE3][NPR2INTERP],
2591  FTYPE (*F1)[NSTORE2][NSTORE3][NPR+NSPECIAL],
2592  FTYPE (*F2)[NSTORE2][NSTORE3][NPR+NSPECIAL],
2593  FTYPE (*F3)[NSTORE2][NSTORE3][NPR+NSPECIAL],
2594  FTYPE CUf,
2595  FTYPE fluxdt,
2596  FTYPE *ndt1,
2597  FTYPE *ndt2,
2598  FTYPE *ndt3
2599  )
2600 {
2601  int dir,i,j,k,pl,pliter;
2602  struct of_geom geomcdontuse;
2603  struct of_geom *ptrgeomc=&geomcdontuse;
2604 
2605  struct of_geom geomf1dontuse;
2606  struct of_geom *ptrgeomf1=&geomf1dontuse;
2607  struct of_geom geomf2dontuse;
2608  struct of_geom *ptrgeomf2=&geomf2dontuse;
2609 
2610  struct of_geom geomf1udontuse;
2611  struct of_geom *ptrgeomf1u=&geomf1udontuse;
2612  struct of_geom geomf2udontuse;
2613  struct of_geom *ptrgeomf2u=&geomf2udontuse;
2614 
2615  struct of_geom geomcorn3dontuse;
2616  struct of_geom *ptrgeomcorn3=&geomcorn3dontuse;
2617  // FTYPE Flux[3][3][NDIM][NPR];
2618  // FTYPE ctop[3][3][NDIM];
2619  FTYPE primcent[3][3][NPR];
2620  FTYPE prim[3][3][NPR];
2621  FTYPE uconf1[3][3][NDIM];
2622  FTYPE uconf2[3][3][NDIM];
2623  FTYPE uconcent[3][3][NDIM];
2624  int ii,jj,kk;
2625  int shifti,shiftj;
2626  FTYPE dtij[NDIM];
2627  //GLOBALMAC(F1,ii,jj,k)
2628  FTYPE emf2d[3][3],c2d[NUMCS][COMPDIM];
2629  FTYPE others[100];
2630  struct of_state state;
2631  FTYPE cminmax[3][3][NUMCS][NDIM];
2632  int ignorecourant=0;
2633  FTYPE dB[2],ctop[2],ctoporig[2];
2634  FTYPE ctopold[NDIM];
2635  FTYPE emffinal;
2636  struct of_state state_c, state_l, state_r;
2637  struct of_state *ptrstate_c, *ptrstate_l, *ptrstate_r;
2638  FTYPE F_c[NPR], F_l[NPR], F_r[NPR];
2639  FTYPE U_c[NPR], U_l[NPR], U_r[NPR];
2640  FTYPE ocminmax_l[NUMCS], ocminmax_r[NUMCS], ocminmax[NUMCS];
2641  FTYPE ocminmaxrad_l[NUMCS], ocminmaxrad_r[NUMCS], ocminmaxrad[NUMCS];
2642  extern int flux_compute(int i, int j, int k, int dir, struct of_geom *geom, FTYPE *cminmax_l, FTYPE *cminmax_r, FTYPE *cminmax, FTYPE ctopmhd, FTYPE *cminmaxrad_l, FTYPE *cminmaxrad_r, FTYPE *cminmaxrad, FTYPE ctoprad, FTYPE CUf, FTYPE *p_l, FTYPE *p_r, FTYPE *U_l, FTYPE *U_r, FTYPE *F_l, FTYPE *F_r, FTYPE *F);
2643  extern int p2SFUevolve(int dir, int isleftright, FTYPE *p, struct of_geom *geom, struct of_state **ptrstate, FTYPE *F, FTYPE *U);
2644  FTYPE ctopother[NDIM];
2645  FTYPE *ctopptr=&ctopother[0];
2646  FTYPE ctopother2[NDIM];
2647  FTYPE *ctopptr2=&ctopother2[0];
2648 
2649  FTYPE ctopradother[NDIM];
2650  FTYPE *ctopradptr=&ctopradother[0];
2651  FTYPE ctopradother2[NDIM];
2652  FTYPE *ctopradptr2=&ctopradother2[0];
2653 
2654  FTYPE F[NPR];
2655  FTYPE p_l[NPR],p_r[NPR];
2656  FTYPE pvec_l[NDIM][NPR],pvec_r[NDIM][NPR];
2657  extern int cminmax_calc(FTYPE cmin_l,FTYPE cmin_r,FTYPE cmax_l,FTYPE cmax_r,FTYPE *cmin,FTYPE *cmax,FTYPE *ctop);
2658  int is,ie,js,je,ks,ke;
2659 
2660 
2661 #if(EOMRADTYPE!=EOMRADNONE)
2662  dualfprintf(fail_file,"fluxcalc_donor not setup for radiation.");
2663  myexit(1);
2664 #endif
2665 
2666 
2667 
2668 
2669 
2670 
2671  // default
2672  ptrstate_c = &state_c;
2673  ptrstate_l = &state_l;
2674  ptrstate_r = &state_r;
2675 
2676  // COMPFULLLOOP{
2677  // COMPZLOOP{
2678  // ODDITY: ADDED EXTRA SHIFT
2679  // ODDITY: ADDED EXTRA LOWER SHIFT
2680 #define MYCOMPLOOPF3 for(k=-SHIFT3+SHIFTX3DN;k<=N3-1+SHIFT3+SHIFT3+SHIFTX3UP;k++)
2681 #define MYCOMPLOOPF2 for(j=-SHIFT2+SHIFTX2DN;j<=N2-1+SHIFT2+SHIFT2+SHIFTX2UP;j++)
2682 #define MYCOMPLOOPF1 for(i=-SHIFT1+SHIFTX1DN;i<=N1-1+SHIFT1+SHIFT1+SHIFTX1UP;i++)
2683  //#define MYCOMPLOOPF3 for(k=0+SHIFTX3DN;k<=N3-1+SHIFT3+SHIFTX3UP;k++)
2684  //#define MYCOMPLOOPF2 for(j=0+SHIFTX2DN;j<=N2-1+SHIFT2+SHIFTX2UP;j++)
2685  //#define MYCOMPLOOPF1 for(i=0+SHIFTX1DN;i<=N1-1+SHIFT1+SHIFTX1UP;i++)
2686 
2687 
2688  //#define MYCOMPLOOPF3 for(k=ks+SHIFTX3DN;k<=ke+SHIFTX3UP;k++)
2689  //#define MYCOMPLOOPF2 for(j=js+SHIFTX2DN;j<=je+SHIFTX2UP;j++)
2690  //#define MYCOMPLOOPF1 for(i=is+SHIFTX1DN;i<=ie+SHIFTX1UP;i++)
2691 
2692 #define MYCOMPLOOPF MYCOMPLOOPF3 MYCOMPLOOPF2 MYCOMPLOOPF1
2693 
2694  MYCOMPLOOPF{
2695  // set primitives (effective interpolation)
2696  kk=0;
2697  for(ii=im1mac(i);ii<=ip1mac(i);ii++){
2698  for(jj=jm1mac(j);jj<=jp1mac(j);jj++){
2699  shifti=1+ii-i;
2700  shiftj=1+jj-j;
2701 
2702  PLOOP(pliter,pl) primcent[shifti][shiftj][pl] = MACP0A1(pr,ii,jj,kk,pl);
2703  PLOOP(pliter,pl) prim[shifti][shiftj][pl] = MACP0A1(pr,ii,jj,kk,pl);
2704  PLOOPBONLY(pl) prim[shifti][shiftj][pl] = MACP0A1(pstag,ii,jj,kk,pl); // replace with face values (should be same really)
2705 
2706  // if(i==390 && j==1 && k==0){
2707  // dualfprintf(fail_file,"i=%d j=%d k=%d prim[B2]=%21.15g\n",ii,jj,k,prim[shifti][shiftj][B2]);
2708  // }
2709 
2710  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2711  ucon_calc(prim[shifti][shiftj], ptrgeomc, uconcent[shifti][shiftj],others);
2712 
2713  // only geometrical difference compared to above
2714  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
2715  ucon_calc(prim[shifti][shiftj], ptrgeomf1, uconf1[shifti][shiftj],others);
2716 
2717  // only geometrical difference compared to above
2718  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
2719  ucon_calc(prim[shifti][shiftj], ptrgeomf2, uconf2[shifti][shiftj],others);
2720 
2721  }
2722  }
2723 
2724 
2725 
2727  // set flux at faces (effective flux_compute)
2728  dir=1;
2729 
2730  ii=i;
2731  jj=j;
2732  kk=k;
2733  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
2734  PLOOP(pliter,pl) p_l[pl] = prim[0][1][pl];
2735  PLOOP(pliter,pl) p_r[pl] = prim[1][1][pl];
2736  p_l[B1]=p_r[B1]=prim[1][1][B1]; // wasn't enforced at first
2737 
2738 
2739  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
2740  get_geometry(ii,jp1mac(jj),kk, FACE2, ptrgeomf2u);
2741  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2742  p_r[B2]=0.5*(prim[1][1][B2]*ptrgeomf2->gdet+prim[1][2][B2]*ptrgeomf2u->gdet)/(ptrgeomc->gdet);
2743  // if(i==390 && j==1 && k==0){
2744  // dualfprintf(fail_file,"ONE: ii=%d jj=%d kk=%d :: %21.15g %21.15g : %21.15g %21.15g : %21.15g\n",ii,jj,kk,prim[1][1][B2],ptrgeomf2->gdet,prim[1][2][B2],ptrgeomf2u->gdet,ptrgeomc->gdet);
2745  // dualfprintf(fail_file,"ONEB: %d %d %d :: %d %d %d :: %d %d %d\n",ii,jj,kk,ii,jp1mac(jj),kk,ii,jj,kk);
2746  // }
2747  get_geometry(im1mac(ii),jj,kk, FACE2, ptrgeomf2);
2748  get_geometry(im1mac(ii),jp1mac(jj),kk, FACE2, ptrgeomf2u);
2749  get_geometry(im1mac(ii),jj,kk, CENT, ptrgeomc);
2750  p_l[B2]=0.5*(prim[0][1][B2]*ptrgeomf2->gdet+prim[0][2][B2]*ptrgeomf2u->gdet)/(ptrgeomc->gdet);
2751  // if(i==390 && j==1 && k==0){
2752  // dualfprintf(fail_file,"TWO: ii=%d jj=%d kk=%d :: %21.15g %21.15g : %21.15g %21.15g : %21.15g\n",ii,jj,kk,prim[0][1][B2],ptrgeomf2->gdet,prim[0][2][B2],ptrgeomf2u->gdet,ptrgeomc->gdet);
2753  // dualfprintf(fail_file,"ONEB: %d %d %d :: %d %d %d :: %d %d %d\n",im1mac(ii),jj,kk,im1mac(ii),jp1mac(jj),kk,im1mac(ii),jj,kk);
2754  // }
2755 
2756  PLOOP(pliter,pl) pvec_l[dir][pl]=p_l[pl];
2757  PLOOP(pliter,pl) pvec_r[dir][pl]=p_r[pl];
2758 
2759  if(0){
2760  // issue with wavespeed?
2761  flux_compute_general(i, j, k, dir, ptrgeomf1, CUf, NULL, p_l, p_r, MAC(F1,i,j,k), &ctopptr[dir]);
2762  }
2763  else{
2764 
2765  MYFUN(p2SFUevolve(dir, ISLEFT, p_l, ptrgeomf1, &ptrstate_l, F_l, U_l),"step_ch.c:fluxcalc()", "p2SFUevolve()", 1);
2766  MYFUN(p2SFUevolve(dir, ISRIGHT, p_r, ptrgeomf1, &ptrstate_r, F_r, U_r),"step_ch.c:fluxcalc()", "p2SFUevolve()", 2);
2767  if(STOREWAVESPEEDMETHOD==0){
2768  // == 0 method
2769  // characteristic based upon t^n level for 1/2 step and t^{n+1/2} level for the full step.
2770  MYFUN(vchar(p_l, ptrstate_l, dir, ptrgeomf1, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2771  MYFUN(vchar(p_r, ptrstate_r, dir, ptrgeomf1, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2772  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr[1]);
2773  }
2774  else{
2775  // ==1 method
2776  get_geometry(im1mac(ii),jj,kk, CENT, ptrgeomc);
2777  get_state(primcent[0][1],ptrgeomc,&state);
2778  MYFUN(vchar(primcent[0][1], &state, dir, ptrgeomc, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2779  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2780  get_state(primcent[1][1],ptrgeomc,&state);
2781  MYFUN(vchar(primcent[1][1], &state, dir, ptrgeomc, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2782  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr[1]);
2783  }
2784 
2785 
2786 
2787  // c2d[CMIN][0] = MAX(0.,-ocminmax[CMIN]);
2788  // c2d[CMAX][0] = MAX(0.,+ocminmax[CMAX]);
2789  // cminmax_calc() already sets the below with positive sign and MAX'ed against zero
2790  c2d[CMIN][0] = ocminmax[CMIN];
2791  c2d[CMAX][0] = ocminmax[CMAX];
2792 
2793  // now get flux
2794  MYFUN(flux_compute(i, j, k, dir, ptrgeomf1, ocminmax_l,ocminmax_r, ocminmax, ctopptr[1], ocminmaxrad_l,ocminmaxrad_r, ocminmaxrad, ctopradptr[1], CUf, p_l, p_r, U_l, U_r, F_l, F_r, F),"step_ch.c:fluxcalc()", "flux_compute", 1);
2795  PLOOP(pliter,pl) MACP0A1(F1,i,j,k,pl)=F[pl];
2796 
2797 #if(0)
2798  // DEBUG:
2799  if(i==390 && j==1 && k==0){
2800  dualfprintf(fail_file,"\n");
2801  PLOOP(pliter,pl) dualfprintf(fail_file,"F1: pl=%d p_l=%21.15g p_r=%21.15g U_l=%21.15g U_r=%21.15g F_l=%21.15g F_r=%21.15g F=%21.15g\n",pl,p_l[pl],p_r[pl],U_l[pl],U_r[pl],F_l[pl],F_r[pl],F[pl]);
2802  dualfprintf(fail_file,"NEW: ocminmax_l[CMIN]=%21.15g ocminmax_r[CMIN]=%21.15g ocminmax_l[CMAX]=%21.15g ocminmax_r[CMAX]=%21.15g ocminmax[CMIN]=%21.15g ocminmax[CMAX]=%21.15g ctopptr[1]=%21.15g\n",ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],ocminmax[CMIN],ocminmax[CMAX],ctopptr[1]);
2803  }
2804 #endif
2805 
2806  // get lower in j for wave speeds for EMF
2807  ii=i;
2808  jj=jm1mac(j);
2809  kk=k;
2810  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
2811  PLOOP(pliter,pl) p_l[pl] = prim[0][0][pl];
2812  PLOOP(pliter,pl) p_r[pl] = prim[1][0][pl];
2813  p_l[B1]=p_r[B1]=prim[1][0][B1]; // wasn't enforced at first
2814 
2815  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
2816  get_geometry(ii,jp1mac(jj),kk, FACE2, ptrgeomf2u);
2817  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2818  p_r[B2]=0.5*(prim[1][0][B2]*ptrgeomf2->gdet+prim[1][1][B2]*ptrgeomf2u->gdet)/(ptrgeomc->gdet);
2819 
2820  get_geometry(im1mac(ii),jj,kk, FACE2, ptrgeomf2);
2821  get_geometry(im1mac(ii),jp1mac(jj),kk, FACE2, ptrgeomf2u);
2822  get_geometry(im1mac(ii),jj,kk, CENT, ptrgeomc);
2823  p_l[B2]=0.5*(prim[0][0][B2]*ptrgeomf2->gdet+prim[0][1][B2]*ptrgeomf2u->gdet)/(ptrgeomc->gdet);
2824 
2825  MYFUN(p2SFUevolve(dir, ISLEFT, p_l, ptrgeomf1, &ptrstate_l, F_l, U_l),"step_ch.c:fluxcalc()", "p2SFUevolve()", 1);
2826  MYFUN(p2SFUevolve(dir, ISRIGHT, p_r, ptrgeomf1, &ptrstate_r, F_r, U_r),"step_ch.c:fluxcalc()", "p2SFUevolve()", 2);
2827 
2828  if(STOREWAVESPEEDMETHOD==0){
2829  // ==0 method
2830  // characteristic based upon t^n level for 1/2 step and t^{n+1/2} level for the full step.
2831  MYFUN(vchar(p_l, ptrstate_l, dir, ptrgeomf1, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2832  MYFUN(vchar(p_r, ptrstate_r, dir, ptrgeomf1, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2833  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr2[1]);
2834  // have cmin,cmax,ctop here
2835  }
2836  else{
2837  // ==1 method
2838  get_geometry(im1mac(ii),jj,kk, CENT, ptrgeomc);
2839  get_state(primcent[0][0],ptrgeomc,&state);
2840  MYFUN(vchar(primcent[0][0], &state, dir, ptrgeomc, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2841  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2842  get_state(primcent[1][0],ptrgeomc,&state);
2843  MYFUN(vchar(primcent[1][0], &state, dir, ptrgeomc, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2844  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr2[1]);
2845  }
2846 
2847  // cminmax_calc() already sets the below with positive sign and MAX'ed against zero
2848  c2d[CMIN][0] = fabs(MAX(c2d[CMIN][0],ocminmax[CMIN]));
2849  c2d[CMAX][0] = fabs(MAX(c2d[CMAX][0],ocminmax[CMAX]));
2850  ctoporig[0] = MAX(c2d[CMIN][0],c2d[CMAX][0]);
2851 
2852  }
2853 
2854 
2856  //
2857  dir=2;
2858 
2859  ii=i;
2860  jj=j;
2861  kk=k;
2862  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
2863  PLOOP(pliter,pl) p_l[pl] = prim[1][0][pl];
2864  PLOOP(pliter,pl) p_r[pl] = prim[1][1][pl];
2865  p_l[B2]=p_r[B2]=prim[1][1][B2]; // wasn't enforced at first
2866 
2867  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
2868  get_geometry(ip1mac(ii),jj,kk, FACE1, ptrgeomf1u);
2869  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2870  p_r[B1]=0.5*(prim[1][1][B1]*ptrgeomf1->gdet+prim[2][1][B1]*ptrgeomf1u->gdet)/(ptrgeomc->gdet);
2871 
2872  get_geometry(ii,jm1mac(jj),kk, FACE1, ptrgeomf1);
2873  get_geometry(ip1mac(ii),jm1mac(jj),kk, FACE1, ptrgeomf1u);
2874  get_geometry(ii,jm1mac(jj),kk, CENT, ptrgeomc);
2875  p_l[B1]=0.5*(prim[1][0][B1]*ptrgeomf1->gdet+prim[2][0][B1]*ptrgeomf1u->gdet)/(ptrgeomc->gdet);
2876 
2877  PLOOP(pliter,pl) pvec_l[dir][pl]=p_l[pl];
2878  PLOOP(pliter,pl) pvec_r[dir][pl]=p_r[pl];
2879 
2880  if(0){
2881  // issue with wavespeed?
2882  flux_compute_general(i, j, k, dir, ptrgeomf2, CUf, NULL, p_l, p_r, MAC(F2,i,j,k), &ctopptr[dir]);
2883  }
2884  else{
2885 
2886  MYFUN(p2SFUevolve(dir, ISLEFT, p_l, ptrgeomf2, &ptrstate_l, F_l, U_l),"step_ch.c:fluxcalc()", "p2SFUevolve()", 1);
2887  MYFUN(p2SFUevolve(dir, ISRIGHT, p_r, ptrgeomf2, &ptrstate_r, F_r, U_r),"step_ch.c:fluxcalc()", "p2SFUevolve()", 2);
2888 
2889  if(STOREWAVESPEEDMETHOD==0){
2890  // == 0 method
2891  // characteristic based upon t^n level for 1/2 step and t^{n+1/2} level for the full step.
2892  MYFUN(vchar(p_l, ptrstate_l, dir, ptrgeomf2, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2893  MYFUN(vchar(p_r, ptrstate_r, dir, ptrgeomf2, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2894  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr[2]);
2895  // have cmin,cmax,ctop here
2896  }
2897  else{
2898  // == 1 method
2899  get_geometry(ii,jm1mac(jj),kk,CENT, ptrgeomc);
2900  get_state(primcent[1][0],ptrgeomc,&state);
2901  MYFUN(vchar(primcent[1][0], &state, dir, ptrgeomc, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2902  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2903  get_state(primcent[1][1],ptrgeomc,&state);
2904  MYFUN(vchar(primcent[1][1], &state, dir, ptrgeomc, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2905  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr[2]);
2906  }
2907 
2908  // cminmax_calc() already sets the below with positive sign and MAX'ed against zero
2909  c2d[CMIN][1] = ocminmax[CMIN];
2910  c2d[CMAX][1] = ocminmax[CMAX];
2911 
2912 
2913  // now get flux
2914  MYFUN(flux_compute(i, j, k, dir, ptrgeomf2, ocminmax_l,ocminmax_r, ocminmax, ctopptr[2], ocminmaxrad_l,ocminmaxrad_r, ocminmaxrad, ctopradptr[2], CUf, p_l, p_r, U_l, U_r, F_l, F_r, F),"step_ch.c:fluxcalc()", "flux_compute", 1);
2915  PLOOP(pliter,pl) MACP0A1(F2,i,j,k,pl)=F[pl];
2916 
2917 #if(0)
2918  // DEBUG:
2919  if(i==390 && j==1 && k==0){
2920  dualfprintf(fail_file,"\n");
2921  // PLOOP(pliter,pl) dualfprintf(fail_file,"prim: pl=%d prim[1][0]=%21.15g prim[1][1]=%21.15g\n",prim[1][0][pl],prim[1][1][pl]);
2922  PLOOP(pliter,pl) dualfprintf(fail_file,"F2: pl=%d p_l=%21.15g p_r=%21.15g U_l=%21.15g U_r=%21.15g F_l=%21.15g F_r=%21.15g F=%21.15g\n",pl,p_l[pl],p_r[pl],U_l[pl],U_r[pl],F_l[pl],F_r[pl],F[pl]);
2923  dualfprintf(fail_file,"NEW: ocminmax_l[CMIN]=%21.15g ocminmax_r[CMIN]=%21.15g ocminmax_l[CMAX]=%21.15g ocminmax_r[CMAX]=%21.15g ocminmax[CMIN]=%21.15g ocminmax[CMAX]=%21.15g ctopptr[1]=%21.15g\n",ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],ocminmax[CMIN],ocminmax[CMAX],ctopptr[2]);
2924  }
2925 #endif
2926 
2927  // get lower in i for wave speeds for EMF
2928  ii=im1mac(i);
2929  jj=j;
2930  kk=k;
2931  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
2932  PLOOP(pliter,pl) p_l[pl] = prim[0][0][pl];
2933  PLOOP(pliter,pl) p_r[pl] = prim[0][1][pl];
2934  p_l[B2]=p_r[B2]=prim[0][1][B2]; // wasn't enforced at first
2935 
2936  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
2937  get_geometry(ip1mac(ii),jj,kk, FACE1, ptrgeomf1u);
2938  get_geometry(ii,jj,kk, CENT, ptrgeomc);
2939  p_r[B1]=0.5*(prim[0][1][B1]*ptrgeomf1->gdet+prim[1][1][B1]*ptrgeomf1u->gdet)/(ptrgeomc->gdet);
2940 
2941  get_geometry(ii,jm1mac(jj),kk, FACE1, ptrgeomf1);
2942  get_geometry(ip1mac(ii),jm1mac(jj),kk, FACE1, ptrgeomf1u);
2943  get_geometry(ii,jm1mac(jj),kk, CENT, ptrgeomc);
2944  p_l[B1]=0.5*(prim[0][0][B1]*ptrgeomf1->gdet+prim[1][0][B1]*ptrgeomf1u->gdet)/(ptrgeomc->gdet);
2945 
2946  MYFUN(p2SFUevolve(dir, ISLEFT, p_l, ptrgeomf2, &ptrstate_l, F_l, U_l),"step_ch.c:fluxcalc()", "p2SFUevolve()", 1);
2947  MYFUN(p2SFUevolve(dir, ISRIGHT, p_r, ptrgeomf2, &ptrstate_r, F_r, U_r),"step_ch.c:fluxcalc()", "p2SFUevolve()", 2);
2948  if(STOREWAVESPEEDMETHOD==0){
2949  // ==0 method
2950  // characteristic based upon t^n level for 1/2 step and t^{n+1/2} level for the full step.
2951  MYFUN(vchar(p_l, ptrstate_l, dir, ptrgeomf2, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2952  MYFUN(vchar(p_r, ptrstate_r, dir, ptrgeomf2, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2953  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr2[2]);
2954  // have cmin,cmax,ctop here
2955  }
2956  else{
2957  // ==1 method
2958  get_geometry(ii,jm1mac(jj),kk,CENT, ptrgeomc);
2959  get_state(primcent[0][0],ptrgeomc,&state);
2960  MYFUN(vchar(primcent[0][0], &state, dir, ptrgeomc, &ocminmax_l[CMAX], &ocminmax_l[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 1);
2961  get_geometry(ii,jj,kk,CENT, ptrgeomc);
2962  get_state(primcent[0][1],ptrgeomc,&state);
2963  MYFUN(vchar(primcent[0][1], &state, dir, ptrgeomc, &ocminmax_r[CMAX], &ocminmax_r[CMIN],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 2);
2964  cminmax_calc(ocminmax_l[CMIN],ocminmax_r[CMIN],ocminmax_l[CMAX],ocminmax_r[CMAX],&ocminmax[CMIN],&ocminmax[CMAX],&ctopptr2[2]);
2965  }
2966 
2967  // cminmax_calc() already sets the below with positive sign and MAX'ed against zero
2968  c2d[CMIN][1] = fabs(MAX(c2d[CMIN][1],ocminmax[CMIN]));
2969  c2d[CMAX][1] = fabs(MAX(c2d[CMAX][1],ocminmax[CMAX]));
2970  ctoporig[1] = MAX(c2d[CMIN][1],c2d[CMAX][1]);
2971 
2972  }
2973 
2974 
2975  // zero-out as test comparison with normal code
2976  if(1){
2977  dir=1; if(i==389) PLOOP(pliter,pl) if(pl!=U1) MACP0A1(F1,i,j,k,pl)=0.0;
2978  dir=1; if(i==419) PLOOP(pliter,pl) if(pl!=U1) MACP0A1(F1,i,j,k,pl)=0.0;
2979  dir=2; if(i==0) PLOOP(pliter,pl) if(pl!=U2) MACP0A1(F2,i,j,k,pl)=0.0;
2980  dir=2; if(i==N2) PLOOP(pliter,pl) if(pl!=U2) MACP0A1(F2,i,j,k,pl)=0.0;
2981  }
2982 
2983 
2985  // now compute correct staggered EMF at CORN3
2986  get_geometry(i,j,k, CORN3, ptrgeomcorn3);
2987 
2988 
2989 #define WHICHEMF 1
2990 
2991 #if(WHICHEMF==0)
2992  // not really spatially correct for emf2d and vchar not like normal code
2993 
2994  // EMF3
2995  kk=0;
2996  for(ii=im1mac(i);ii<=ip1mac(i);ii++){
2997  for(jj=jm1mac(j);jj<=jp1mac(j);jj++){
2998  shifti=1+ii-i;
2999  shiftj=1+jj-j;
3000 
3001  // use uconf1 with B1 since that's how packed for interpolation in normal routine. Can try alternatives.
3002  // emf_3 = gdet(B^2 v^1 - B^1 v^2) = F1[B2] or -F2[B1]
3003  emf2d[shifti][shiftj] = (
3004  // + prim[shifti][shiftj][B1]*uconf1[shifti][shiftj][2]/uconf1[shifti][shiftj][TT]
3005  // - prim[shifti][shiftj][B2]*uconf2[shifti][shiftj][1]/uconf2[shifti][shiftj][TT]
3006  + prim[shifti][shiftj][B2]*uconf2[shifti][shiftj][1]/uconf2[shifti][shiftj][TT]
3007  - prim[shifti][shiftj][B1]*uconf1[shifti][shiftj][2]/uconf1[shifti][shiftj][TT]
3008  );
3009 
3010  // GODMARK: vchar directly at CORN3, which is different than averaging procedure done in normal code
3011  get_state(prim[shifti][shiftj], ptrgeomcorn3, &state);
3012  dir=1; MYFUN(vchar(prim[shifti][shiftj], &state, dir, ptrgeomcorn3, &cminmax[shifti][shiftj][CMAX][dir], &cminmax[shifti][shiftj][CMIN][dir],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 10);
3013  dir=2; MYFUN(vchar(prim[shifti][shiftj], &state, dir, ptrgeomcorn3, &cminmax[shifti][shiftj][CMAX][dir], &cminmax[shifti][shiftj][CMIN][dir],&ignorecourant),"step_ch.c:fluxcalc()", "vchar() dir=1or2", 11);
3014 
3015 
3016  // dualfprintf(fail_file,"i=%d j=%d k=%d ii=%d jj=%d kk=%d ",i,j,k,ii,jj,kk);
3017  // PLOOP(pliter,pl) dualfprintf(fail_file,"prim[%d]=%21.15g ",pl,prim[shifti][shiftj][pl]);
3018  // dualfprintf(fail_file,"\n");
3019  }
3020  }
3021 
3022  // use vchar generated at CORN3
3023  //c[CMIN,CMAX][0=odir1,1=odir2]
3024  // dir=1:
3025  ctop[0] = MAX((-cminmax[0][0][CMIN][1]),(-cminmax[1][0][CMIN][1]));
3026  ctop[0] = MAX(ctop[0],(-cminmax[0][1][CMIN][1]));
3027  ctop[0] = MAX(ctop[0],(-cminmax[1][0][CMIN][1]));
3028  ctop[0] = MAX(ctop[0],(-cminmax[1][1][CMIN][1]));
3029  ctop[0] = MAX(ctop[0],0.0);
3030 
3031  ctop[0] = MAX(ctop[0],(cminmax[0][0][CMAX][1]));
3032  ctop[0] = MAX(ctop[0],(cminmax[1][0][CMAX][1]));
3033  ctop[0] = MAX(ctop[0],(cminmax[0][1][CMAX][1]));
3034  ctop[0] = MAX(ctop[0],(cminmax[1][1][CMAX][1]));
3035 
3036  // dir=2:
3037  ctop[1] = MAX((-cminmax[0][0][CMIN][2]),(-cminmax[1][0][CMIN][2]));
3038  ctop[1] = MAX(ctop[1],(-cminmax[0][1][CMIN][2]));
3039  ctop[1] = MAX(ctop[1],(-cminmax[1][0][CMIN][2]));
3040  ctop[1] = MAX(ctop[1],(-cminmax[1][1][CMIN][2]));
3041  ctop[1] = MAX(ctop[1],0.0);
3042 
3043  ctop[1] = MAX(ctop[1],(cminmax[0][0][CMAX][2]));
3044  ctop[1] = MAX(ctop[1],(cminmax[1][0][CMAX][2]));
3045  ctop[1] = MAX(ctop[1],(cminmax[0][1][CMAX][2]));
3046  ctop[1] = MAX(ctop[1],(cminmax[1][1][CMAX][2]));
3047 
3048  // use vchar generated and "max-averaged" as in normal code
3049  // ctop[0] = ctoporig[0];
3050  // ctop[1] = ctoporig[1];
3051 
3052 #else
3053 
3054  // 1 1
3055  ii=i;
3056  jj=j;
3057  kk=k;
3058  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
3059  ucon_calc(primcent[1][1], ptrgeomf1, uconf1[1][1],others);
3060 
3061  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
3062  ucon_calc(primcent[1][1], ptrgeomf2, uconf2[1][1],others);
3063 
3064  emf2d[1][1] = (
3065  + prim[1][1][B2]*uconf2[1][1][1]/uconf2[1][1][TT]
3066  - prim[1][1][B1]*uconf1[1][1][2]/uconf1[1][1][TT]
3067  );
3068 
3069  // 0 1
3070  ii=im1mac(i);
3071  jj=j;
3072  kk=k;
3073  get_geometry(ii+1,jj,kk, FACE1, ptrgeomf1);
3074  ucon_calc(primcent[0][1], ptrgeomf1, uconf1[0][1],others);
3075 
3076  get_geometry(ii,jj,kk, FACE2, ptrgeomf2);
3077  ucon_calc(primcent[0][1], ptrgeomf2, uconf2[0][1],others);
3078 
3079  emf2d[0][1] = (
3080  + prim[0][1][B2]*uconf2[0][1][1]/uconf2[0][1][TT]
3081  - prim[1][1][B1]*uconf1[0][1][2]/uconf1[0][1][TT]
3082  );
3083 
3084  // 1 0
3085  ii=i;
3086  jj=jm1mac(j);
3087  kk=k;
3088  get_geometry(ii,jj,kk, FACE1, ptrgeomf1);
3089  ucon_calc(primcent[1][0], ptrgeomf1, uconf1[1][0],others);
3090 
3091  get_geometry(ii,jj+1,kk, FACE2, ptrgeomf2);
3092  ucon_calc(primcent[1][0], ptrgeomf2, uconf2[1][0],others);
3093 
3094  emf2d[1][0] = (
3095  + prim[1][1][B2]*uconf2[1][0][1]/uconf2[1][0][TT]
3096  - prim[1][0][B1]*uconf1[1][0][2]/uconf1[1][0][TT]
3097  );
3098 
3099  // 0 0
3100  ii=im1mac(i);
3101  jj=jm1mac(j);
3102  kk=k;
3103  get_geometry(ii+1,jj,kk, FACE1, ptrgeomf1);
3104  ucon_calc(primcent[0][0], ptrgeomf1, uconf1[0][0],others);
3105 
3106  get_geometry(ii,jj+1,kk, FACE2, ptrgeomf2);
3107  ucon_calc(primcent[0][0], ptrgeomf2, uconf2[0][0],others);
3108 
3109  emf2d[0][0] = (
3110  + prim[0][1][B2]*uconf2[0][0][1]/uconf2[0][0][TT]
3111  - prim[1][0][B1]*uconf1[0][0][2]/uconf1[0][0][TT]
3112  );
3113 
3114  // don't compute cminmax[][][CMIN/CMAX][dir] since not needed
3115 
3116  // use vchar generated and "max-averaged" as in normal code
3117  ctop[0] = ctoporig[0];
3118  ctop[1] = ctoporig[1];
3119 #endif
3120 
3121 
3122 
3123  //edgedir=3 odir1=1 odir2=2
3124  // dB in perp to B-dir at CORN3
3125  // dir=1:
3126  dB[0] = prim[1][1][B1]-prim[1][0][B1];
3127  // dir=2:
3128  dB[1] = prim[1][1][B2]-prim[0][1][B2];
3129 
3130 
3131  emffinal=(
3132  + 0.25*(emf2d[0][0]+emf2d[0][1]+emf2d[1][0]+emf2d[1][1])
3133  - 0.50*(ctop[0]*dB[1] - ctop[1]*dB[0])
3134  );
3135 
3136 #if(0)
3137  // DEBUG:
3138  if(i==390 && j==1 && k==0){
3139  dualfprintf(fail_file,"NEW: emf2d[1][1]=%21.15g emf2d[1][0]=%21.15g emf2d[0][1]=%21.15g emf2d[0][0]=%21.15g ctop[0]=%21.15g ctop[1]=%21.15g dB[0]=%21.15g dB[1]=%21.15g emffinal=%21.15g gdetcorn3=%21.15g\n",emf2d[1][1],emf2d[1][0],emf2d[0][1],emf2d[0][0],ctop[0],ctop[1],dB[0],dB[1],emffinal,ptrgeomcorn3->gdet);
3140  dualfprintf(fail_file,"NEW: c2d[CMIN][0]=%21.15g c2d[CMAX][0]=%21.15g c2d[CMIN][1]=%21.15g c2d[CMAX][1]=%21.15g\n",c2d[CMIN][0],c2d[CMAX][0],c2d[CMIN][1],c2d[CMAX][1]);
3141  }
3142 #endif
3143 
3144  emffinal *= (ptrgeomcorn3->gdet);
3145 
3146  // zero-out as test comparison with normal code
3147  if(1){
3148  if(i==389) emffinal=0.0;
3149  if(i==419) emffinal=0.0;
3150  // ODDITY: Nan grabbed at 419 with i+1 by ucum_check() [only for field]
3151  if(i==419+1) emffinal=0.0;
3152  if(j==0) emffinal=0.0;
3153  if(j==N2) emffinal=0.0;
3154  // if(i==N2+1) emffinal=0.0;
3155  }
3156 
3157  MACP0A1(F1,i,j,k,B2) = emffinal;
3158  MACP0A1(F2,i,j,k,B1) = -MACP0A1(F1,i,j,k,B2);
3159 
3160  // dualfprintf(fail_file,"nstep=%ld steppart=%d :: i=%d j=%d k=%d :: %21.15g %21.15g\n",nstep,steppart,i,j,k,MACP0A1(F1,i,j,k,B1),MACP0A1(F2,i,j,k,B2));
3161  // ODDLY: required below to preserve divb=0
3162  // NOT ODD, diffusive term will be c*(dB1) and c*(dB2) despite zero non-diffusive flux.
3163  // Well, diffusive term is zero once set staggered field -> face flux correctly
3164  MACP0A1(F1,i,j,k,B1) = 0.0;
3165  MACP0A1(F2,i,j,k,B2) = 0.0;
3166 
3167 
3168  // set dt
3169  if(WITHINACTIVESECTIONEXPAND1(i,j,k)){
3170  // dualfprintf(fail_file,"INSIDEDTCHECK: nstep=%ld steppart=%d i=%d j=%d k=%d\n",nstep,steppart,i,j,k);
3171  dir=1;
3172  dtij[dir] = cour * dx[dir] / ctopptr[dir]; // use wave speed from face flux calculation
3173  //loop over the interfaces where fluxes are computed -- atch, useCOMPZSLOOP( is, ie, js, je, ks, ke ) { ... }
3174  is=fluxloop[dir][FIS]+SHIFTX1DN;
3175  ie=fluxloop[dir][FIE]+SHIFTX1UP;
3176  js=fluxloop[dir][FJS]+SHIFTX2DN;
3177  je=fluxloop[dir][FJE]+SHIFTX2UP;
3178  ks=fluxloop[dir][FKS]+SHIFTX3DN;
3179  ke=fluxloop[dir][FKE]+SHIFTX3UP;
3180  if(dtij[dir]<*ndt1 && i>=is && i<=ie && j>=js && j<=je && k>=ks && k<=ke){ // mimics normal code
3181  *ndt1=dtij[dir];
3182  dualfprintf(fail_file,"NEW: Got lower dir=%d i=%d j=%d k=%d ndt=%21.15g\n",dir,i,j,k,*ndt1);
3183  }
3184 
3185  dir=2;
3186  dtij[dir] = cour * dx[dir] / ctopptr[dir]; // use wave speed from face flux calculation
3187  is=fluxloop[dir][FIS]+SHIFTX1DN;
3188  ie=fluxloop[dir][FIE]+SHIFTX1UP;
3189  js=fluxloop[dir][FJS]+SHIFTX2DN;
3190  je=fluxloop[dir][FJE]+SHIFTX2UP;
3191  ks=fluxloop[dir][FKS]+SHIFTX3DN;
3192  ke=fluxloop[dir][FKE]+SHIFTX3UP;
3193  if(dtij[dir]<*ndt2 && i>=is && i<=ie && j>=js && j<=je && k>=ks && k<=ke){ // mimics normal code
3194  *ndt2=dtij[dir];
3195  dualfprintf(fail_file,"NEW: Got lower dir=%d i=%d j=%d k=%d ndt=%21.15g\n",dir,i,j,k,*ndt2);
3196  }
3197  }
3198  }
3199 
3200  FTYPE (**ptrfluxvec)[NSTORE2][NSTORE3][NPR+NSPECIAL];
3201  FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL];
3202  int Nvec[NDIM];
3203  int cleanup_fluxes(int *Nvec, FTYPE (*fluxvec[NDIM])[NSTORE2][NSTORE3][NPR+NSPECIAL]);
3204 
3205  fluxvec[1]=F1;
3206  fluxvec[2]=F2;
3207  fluxvec[3]=F3;
3208 
3209  ptrfluxvec=fluxvec;
3210 
3211  Nvec[1]=N1;
3212  Nvec[2]=N2;
3213  Nvec[3]=N3;
3214 
3215  dualfprintf(fail_file,"BEFORE CLEAN\n");
3216  cleanup_fluxes(Nvec,ptrfluxvec);
3217  dualfprintf(fail_file,"AFTER CLEAN\n");
3218 
3219 
3220 
3221  return(0);
3222 
3223 
3224 }