HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
initbase.enerregions.c
Go to the documentation of this file.
1 
7 #include "decs.h"
8 
9 
10 // initialize enerregion LOOP: ENERREGIONLOOP()
11 // No user/problem-dependent code here
12 void reset_dothisenerregion(int initialcall)
13 {
14  int enerregion;
15 
16  // these set some "enerregions"
17  // first set which ener regions to do
18  ENERREGIONALLLOOP(enerregion) dothisenerreg[enerregion]=1;
19  // turn off some enerregions
20  if(DOGRIDSECTIONING==0){
23  }
24  if(DOJETDIAG==0){
27  }
28 }
29 
30 
31 
32 
33 
34 // universal function to recompute boundaries for enerregions and ACTIVEREGION
35 // initialcall: 0 : not initial call, just normal evolution call
36 // initialcall: 1 : true initial call -- probably first time function called
37 // intiialcall: 2 : probably not true initial call, but for GRIDSECTION still treat as first call since still need full COMP loops
38 // initialcall: 3 : not true initial call, but force update to GRIDSECTION
39 // No user/problem-dependent code here
40 // Can't assume recompute_fluxpositions() called *every* timestep or substep. Some steps might be skipped for various reasons to avoid grid changes
41 int recompute_fluxpositions(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
42 {
43  int normalinitialcall;
44  int compinitialcall;
45 
46  // put here anything when changing horizonti (apart from recomputing metric, which is done outside)
47  // if got here then horizonti changed, so need new positions of fluxes
48 
49  if(initialcall==2){
50  compinitialcall=1;
51  normalinitialcall=initialcall;
52  }
53  else if(initialcall==3){
54  compinitialcall=-1;
55  normalinitialcall=initialcall;
56  }
57  else{
58  compinitialcall=initialcall;
59  normalinitialcall=initialcall;
60  }
61 
62  if(normalinitialcall==1){
63  // (equivalent to horizon not existing -- just normal gridding)
64  horizoni = 0;
65  horizoncpupos1 = 0;
66  }
67  else{
68  // otherwise assume set from outside already
69  }
70 
71 
72 
73  // set enerregions
74  // must be done before any ENERREGIONLOOP() call
75  reset_dothisenerregion(normalinitialcall);
76 
77  // set enerregions
78  setflux(normalinitialcall,timeorder,numtimeorders,thenstep,thetime);
79  sethorizonflux(normalinitialcall,timeorder,numtimeorders,thenstep,thetime);
80  settrueglobalregion(normalinitialcall,timeorder,numtimeorders,thenstep,thetime);
81 
82  if(DOJETDIAG) setjetflux(normalinitialcall,timeorder,numtimeorders,thenstep,thetime);
83 
84 
85 
86  // set ACTIVEREGION
87  // should come after other definitions of enerregions in case they are used to define activeregion!
88  if(DOGRIDSECTIONING){
89  setgridsectioning(compinitialcall,timeorder, numtimeorders, nstep,t);
90  }
91 
92 
93  return(0);
94 
95 }
96 
97 
98 
99 
100 // Universal function, where one provides absolute integer grid positions, then it determine ener loop ranges and flux boundaries for provided region and +boundary version if desired
101 // No user/problem-dependent code here
102 // OPENMPMARK: Assume setgeneral_enerregion() not called by multiple threads, so ok to have static and firsttime.
103 int setgeneral_enerregion(int (*enerregiondef)[NDIM], int doprintout, int whichregion, int whichbndregion)
104 {
105  int dimen;
106  int dir;
107  int dirsign;
108  int enerregion,enerregionglobal;
109  int local_enerregiondef[NUMUPDOWN][NDIM];
110  FTYPE X[NDIM],V[NDIM];
111  int Nvec[NDIM];
112  int Nbndvec[NDIM];
113  int ti,tj,tk;
114  int updowniter;
115  int updowniteri,updowniterj,updowniterk;
116  int rind,rindglobal;
117  int *localenerpos,*localenerposglobal;
118  int *localdoflux,*localdofluxglobal;
119  static int firsttime=1;
120  static int previouslysetglobal_enerregiondef[NUMENERREGIONS];
121  int totaldiff;
122  int SHIFTdimen[NDIM];
123 
124 
125 #if(USEOPENMP)
126  if(omp_in_parallel()){
127  dualfprintf(fail_file,"setgeneral_enerregion() called in parallel region\n");
128  myexit(853736);
129  }
130 #endif
131 
133  //
134  // initialize check if previously set global_enerregiondef[]
135  //
137  if(firsttime){
138  ENERREGIONLOOP(enerregion) previouslysetglobal_enerregiondef[enerregion]=0;
139  firsttime=0;
140  }
141 
142 
143 
144 
146  //
147  // setup pointers and perform some checks
148  //
150  Nvec[0]=0;
151  Nvec[1]=N1;
152  Nvec[2]=N2;
153  Nvec[3]=N3;
154 
155  Nbndvec[0]=0;
156  Nbndvec[1]=N1BND;
157  Nbndvec[2]=N2BND;
158  Nbndvec[3]=N3BND;
159 
160 
161  if(whichregion!=NULLENERREGIONS){
162  enerregion=whichregion;
163  localenerpos=enerposreg[enerregion]; //activesection
164  localdoflux=dofluxreg[enerregion]; //activefluxsection
165 
166  if(previouslysetglobal_enerregiondef[whichregion]==1){
167 
168  // see if anything actually changed
169  totaldiff=0;
170  DIMENLOOP(dimen){
171  for(updowniter=0;updowniter<NUMUPDOWN;updowniter++){
172  // GLOBALMARK
173  totaldiff += abs(global_enerregiondef[enerregion][updowniter][dimen] - enerregiondef[updowniter][dimen]);
174  }
175  }
176 
177  if(totaldiff>0){
178  // check if exposing more than N?BND cells
179  DIMENLOOP(dimen){
180  updowniter=POINTDOWN;
181  if(global_enerregiondef[enerregion][updowniter][dimen] - enerregiondef[updowniter][dimen]>Nbndvec[dimen]){
182  // then exposing and too large an exposure for normal bound call
183  dualfprintf(fail_file,"SUPERWARNING!!! : Exposing more cells than bounded on inner boundary: enerregion=%d updowniter=%d dimen=%d\n",enerregion,updowniter,dimen);
184  }
185  updowniter=POINTUP;
186  if(enerregiondef[updowniter][dimen]-global_enerregiondef[enerregion][updowniter][dimen]>Nbndvec[dimen]){
187  // then exposing and too large an exposure for normal bound call
188  dualfprintf(fail_file,"SUPERWARNING!!! : Exposing more cells than bounded on outer boundary: enerregion=%d updowniter=%d dimen=%d\n",enerregion,updowniter,dimen);
189  }
190  }// dimen loop
191  }
192 
193  }// if previously set global_enerregiondef[][][]
194  else{
195  totaldiff=NUMUPDOWN*COMPDIM; // note that there at least should be a change since undefined at first
196  }
197 
198 
199  // now that checks are complete, set global section definition for restart purposes and future check purposes
200  DIMENLOOP(dimen){
201  for(updowniter=0;updowniter<NUMUPDOWN;updowniter++){
202  // GLOBALMARK
203  global_enerregiondef[enerregion][updowniter][dimen] = enerregiondef[updowniter][dimen];
204  }
205  }
206 
207  // now note that previously set global_enerregiondef[][][] so can operate checks
208  previouslysetglobal_enerregiondef[whichregion]=1;
209 
210  }
211 
212 
213 
215  //
216  // check if anything to do/change
217  //
219  if(totaldiff==0){
220  // then nothing to do/change, so just quit
221  return(0);
222  }
223 
224 
225 
227  //
228  // setup pointers for +bnd version of grid (only relevant if normal enerregion done)
229  //
231  if(whichbndregion!=NULLENERREGIONS){
232 
233  if(whichregion==NULLENERREGIONS){
234  dualfprintf(fail_file,"For now assume normal enerregion must exist for bnd region to exist. This is so enerregiondef[][] remains well-defined, which applies to both versions.\n");
235  myexit(896746644);
236  }
237 
238 
239  enerregionglobal=whichbndregion;
240  localenerposglobal=enerposreg[enerregionglobal]; //activewithbndsection
241  localdofluxglobal=dofluxreg[enerregionglobal]; //activewithbndfluxsection
242 
243  // for restart, recompute_fluxpositions() will redo bnd-dependent regions
244  }
245 
246 
247 
248  // for enerpos: loop range for this CPU
249 
250  // for doflux: flux boundary for this CPU
251  // only 0 through N-1 mean do flux
252 
253  // doflux<0 means ignore this cpu in flux calculation
254  // doflux>=0 is used to set where flux is computed.
255  // If dimension exists (i.e. N>1), then OUTM = N is outer flux on boundary
256  // If dimension doesn't exist, then no such outer flux or outer boundary, so stay on same boundary (e.g., i=0) rather than i=N.
257 
258 
259  SHIFTdimen[0]=0;
260  SHIFTdimen[1]=SHIFT1;
261  SHIFTdimen[2]=SHIFT2;
262  SHIFTdimen[3]=SHIFT3;
263 
264 
266  //
267  //define relative indices for active section boundaries
268  //
270  DIMENLOOP(dimen){
271 
272  // define this CPUs relative section position
273  for(updowniter=0;updowniter<NUMUPDOWN;updowniter++){
274  local_enerregiondef[updowniter][dimen] = enerregiondef[updowniter][dimen] - startpos[dimen];
275  }
276 
277 
278  dirsign=-1;
279 
280  if(whichregion!=NULLENERREGIONS){
281  //active section interacts with the current processor
282  rind=localenerpos[DIRFROMDIMEN(dimen,dirsign)] = MAX( 0, local_enerregiondef[POINTDOWN][dimen] );
283  int rindflux=local_enerregiondef[POINTDOWN][dimen];
284  if( Nvec[dimen]>1 && rindflux >= 0 && rindflux < Nvec[dimen] ){
285  localdoflux[DIRFROMDIMEN(dimen,dirsign)]=rindflux;
286  if(doprintout) logfprintf("proc: %d doing enerregion=%d flux %d rind=%d\n",myid,enerregion,DIRFROMDIMEN(dimen,dirsign),rind);
287  }
288  else localdoflux[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
289  }
290 
291 
292  if(whichbndregion!=NULLENERREGIONS){
293  rindglobal=localenerposglobal[DIRFROMDIMEN(dimen,dirsign)] = MAX( -Nbndvec[dimen], local_enerregiondef[POINTDOWN][dimen]-Nbndvec[dimen] );
294  int rindglobalflux=local_enerregiondef[POINTDOWN][dimen]-Nbndvec[dimen];
295  if( Nvec[dimen]>1 && rindglobalflux >= -Nbndvec[dimen] && rindglobalflux < Nvec[dimen]+Nbndvec[dimen] ){
296  localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=rindglobalflux;
297  if(doprintout) logfprintf("proc: %d doing enerregion=%d sectionflux %d rindglobal=%d\n",myid,enerregionglobal,DIRFROMDIMEN(dimen,dirsign),rindglobal);
298  }
299  else localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
300  }
301 
302  dirsign=1;
303 
304  if(whichregion!=NULLENERREGIONS){
305  rind = localenerpos[DIRFROMDIMEN(dimen,dirsign)] = MIN( Nvec[dimen]-1, local_enerregiondef[POINTUP][dimen] );
306  int rindflux = local_enerregiondef[POINTUP][dimen];
307  //(local_enerregiondef[POINTUP][dimen]+1) is the location of face index
308  if( Nvec[dimen]>1 && rindflux >= 0 && rindflux < Nvec[dimen] ){
309  localdoflux[DIRFROMDIMEN(dimen,dirsign)]=rindflux + SHIFTdimen[dimen]; //need to add 1 to get upper edge index for the face given rind is cell center index
310  if(doprintout) logfprintf("proc: %d doing enerregion=%d flux %d rind=%d\n",myid,enerregion,DIRFROMDIMEN(dimen,dirsign),rind);
311  }
312  else localdoflux[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
313  }
314 
315  if(whichbndregion!=NULLENERREGIONS){
316  rindglobal = localenerposglobal[DIRFROMDIMEN(dimen,dirsign)] = MIN( Nvec[dimen]-1+Nbndvec[dimen], local_enerregiondef[POINTUP][dimen]+Nbndvec[dimen] );
317  int rindglobalflux = local_enerregiondef[POINTUP][dimen]+Nbndvec[dimen];
318  if( Nvec[dimen]>1 && rindglobalflux >= -Nbndvec[dimen] && rindglobalflux < Nvec[dimen]+Nbndvec[dimen] ){
319  // localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=rindglobal + SHIFTdimen[dimen]; //need to add 1 to get upper edge index for the face given rindglobal is cell center index
320  localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=rindglobalflux; // +1 value isn't set generally by BC's. flux for this type of quantity not useful once beyond box anyways
321  if(doprintout) logfprintf("proc: %d doing enerregion=%d flux %d using rindglobal=%d\n",myid,enerregionglobal,DIRFROMDIMEN(dimen,dirsign),rindglobal);
322  }
323  else localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
324  }
325 
326  }
327 
328 
329 
330 
331  if(whichregion!=NULLENERREGIONS){
332  // check if really on grid
333  if(localenerpos[X1UP]<localenerpos[X1DN] && Nvec[1]>1 || localenerpos[X2UP]<localenerpos[X2DN] && Nvec[2]>1 || localenerpos[X3UP]<localenerpos[X3DN] && Nvec[3]>1){
334  DIMENLOOP(dimen){
335  dirsign=-1;
336  localdoflux[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
337  dirsign=1;
338  localdoflux[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
339  }
340  }
341  }
342  if(whichbndregion!=NULLENERREGIONS){
343  // check if really on grid
344  if(localenerposglobal[X1UP]<localenerposglobal[X1DN] && Nvec[1]>1 || localenerposglobal[X2UP]<localenerposglobal[X2DN] && Nvec[2]>1 || localenerposglobal[X3UP]<localenerposglobal[X3DN] && Nvec[3]>1){
345  DIMENLOOP(dimen){
346  dirsign=-1;
347  localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
348  dirsign=1;
349  localdofluxglobal[DIRFROMDIMEN(dimen,dirsign)]=FLUXNOTONGRID;
350  }
351  }
352  }
353 
355  //
356  // Print out some diagnostic information about this enerregion
357  //
359 
360  // only print if user desires and there really was a change
361  if(doprintout && totaldiff>0){
362  // fluxes are on edges of zone, so 0 and N are on edge fluxes
363  if(!specialstep){
364  if(whichregion!=NULLENERREGIONS){
365  DIRLOOP(dir) logfprintf("proc: %d enerregion=%d: doflux[%d]=%d enerpos[%d]=%d\n",myid,enerregion,dir,localdoflux[dir],dir,localenerpos[dir]);
366  }
367  if(whichbndregion!=NULLENERREGIONS){
368  DIRLOOP(dir) logfprintf("proc: %d enerregion=%d: doflux[%d]=%d enerpos[%d]=%d\n",myid,enerregionglobal,dir,localdofluxglobal[dir],dir,localenerposglobal[dir]);
369  }
370  }
371  }
372 
374  //
375  // fluxes are on edges of zone, so 0 and N are on edge fluxes
376  //
378  // only print if user desires and there really was a change
379  if(doprintout && totaldiff>0){
380  if(whichregion!=NULLENERREGIONS){ // only print out non-bnd region
381  DIRLOOP(dir) logfprintf("proc: myid=%d :: t=%21.15g nstep=%ld enerregion=%d section: totaldiff=%d localdoflux[%d]=%d localenerpos[%d]=%d\n",myid,t,nstep,enerregion,totaldiff,dir,localdoflux[dir],dir,localenerpos[dir]);
382 
383  // full 3D cube outputted (2^3=8 3D points)
384  for(updowniteri=NUMUPDOWN-1;updowniteri>=0;updowniteri--) for(updowniterj=NUMUPDOWN-1;updowniterj>=0;updowniterj--) for(updowniterk=NUMUPDOWN-1;updowniterk>=0;updowniterk--){
385  ti=enerregiondef[updowniteri][1] + (updowniteri==POINTUP);
386  tj=enerregiondef[updowniterj][2] + (updowniterj==POINTUP);
387  tk=enerregiondef[updowniterk][3] + (updowniterk==POINTUP);
388  // Can't use bl_coord_ijk() or bl_coord_ijk2() below since generally know that i,j,k requested can be beyond stored grid
389  bl_coord_coord( ti, tj, tk, CORNT, X, V );
390  logfprintf( "t = %21.15g, ud_{i,j,k} = %d %d %d :: CORNT_enerregiondef_{i,j,k} = %d %d %d :: V_{1,2,3} = %21.15g %21.15g %21.15g \n", t, updowniteri, updowniterj, updowniterk, ti, tj, tk, V[1], V[2], V[3] );
391 
392  }
393  }
394  }
395 
396  return( 0 );
397 }
398 
399 
400 
401 
402 
403 
404 // enerregion that is ignorant of horizon -- just total computational domain
405 int setflux(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
406 {
407  int enerregion;
408  int enerregiondef[NUMUPDOWN][NDIM];
409  int doprintout;
410 
411 
412  // which enerregion to create
413  enerregion=GLOBALENERREGION;
414 
415  // set enerregiondef[][]
416  setflux_set_enerregiondef(initialcall, timeorder, numtimeorders, thenstep, thetime, enerregiondef );
417 
418  // get region and its additional boundary region
419  doprintout=!specialstep && initialcall==1;
420  setgeneral_enerregion(enerregiondef, doprintout, enerregion, NULLENERREGIONS);
421 
422  return(0);
423 }
424 
425 
426 // actual definition of enerregion for setflux()
427 int setflux_set_enerregiondef(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int (*enerregiondef)[NDIM] )
428 {
429 
430  // normal full total grid
431  enerregiondef[POINTDOWN][1]=0;
432  enerregiondef[POINTUP][1]=totalsize[1]-1;
433  enerregiondef[POINTDOWN][2]=0;
434  enerregiondef[POINTUP][2]=totalsize[2]-1;
435  enerregiondef[POINTDOWN][3]=0;
436  enerregiondef[POINTUP][3]=totalsize[3]-1;
437 
438  return(0);
439 }
440 
441 
442 
443 
444 
445 // enerregion that includes horizon
446 // assumes horizoni and horizoncpupos1 set by find_horizon before this function called
447 int sethorizonflux(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
448 {
449  int enerregion;
450  int enerregiondef[NUMUPDOWN][NDIM];
451  int doprintout;
452 
453 
454  // which enerregion to create
455  enerregion=OUTSIDEHORIZONENERREGION;
456 
457  // set enerregiondef[][]
458  sethorizonflux_set_enerregiondef(initialcall, timeorder, numtimeorders, thenstep, thetime, enerregiondef );
459 
460  // get region and its additional boundary region
461  doprintout=!specialstep && initialcall==1;
462  setgeneral_enerregion(enerregiondef, doprintout, enerregion, NULLENERREGIONS);
463 
464  return(0);
465 }
466 
467 
468 // determine if this cpu is doing what flux through horizon
469 // assumes horizoni and horizoncpupos1 set by find_horizon before this function called
470 int sethorizonflux_set_enerregiondef(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int (*enerregiondef)[NDIM] )
471 {
472 
473  // entire region outside horizon
474  enerregiondef[POINTDOWN][1]=horizoni+horizoncpupos1*N1;
475  enerregiondef[POINTUP][1]=totalsize[1]-1;
476  enerregiondef[POINTDOWN][2]=0;
477  enerregiondef[POINTUP][2]=totalsize[2]-1;
478  enerregiondef[POINTDOWN][3]=0;
479  enerregiondef[POINTUP][3]=totalsize[3]-1;
480 
481  return(0);
482 }
483 
484 
485 
486 // enerregion where quantities are evolved (true global region)
487 // this can be used to determine where quantities are evolved and so active domain only
488 // assumes horizoni and horizoncpupos1 set by find_horizon before this function called
489 int settrueglobalregion(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
490 {
491  int enerregion,enerbndregion;
492  int enerregiondef[NUMUPDOWN][NDIM];
493  int doprintout;
494 
495 
496  // which enerregion to create
497  enerregion=TRUEGLOBALENERREGION;
498  // this ranges over entire domain where ANYTHING is done at all
499  // This is used to avoid any unnecessary access to cells that will never be used
500  enerbndregion=TRUEGLOBALWITHBNDENERREGION;
501 
502  // set enerregiondef[][]
503  settrueglobalregion_set_enerregiondef(initialcall, timeorder, numtimeorders, thenstep, thetime, enerregiondef );
504 
505  // get region and its additional boundary region
506  doprintout=!specialstep && initialcall==1;
507  setgeneral_enerregion(enerregiondef, doprintout, enerregion, enerbndregion);
508 
509  return(0);
510 }
511 
512 
513 
514 int settrueglobalregion_set_enerregiondef(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int (*enerregiondef)[NDIM] )
515 {
516 
517  // entire region outside horizon
518  // below tries to say that inside horizoni-1-N1BND the evolution doesn't matter so ignore it.
519  // used, e.g., in advance.c. However, so that rest of code doesn't have to change, must ensure that
520  // the other zones are set to something so no Nan's and need to be set such that time-like (e.g. for boundprim())
521  // otherwise can go through code and base loops on this enerregion
522  // if(horizoni>0 && horizoncpupos1==0){
523  // // horizoni-1 accounts for fact that horizoni is ceil() of horizon position, not floor()
524  // enerregiondef[POINTDOWN][1]=MAX(0,horizoni-1+horizoncpupos1*N1-N1BND);
525  // }
526  // else{
527  // standard case:
528  // should be no smaller than 0
529  enerregiondef[POINTDOWN][1]=MAX(0,horizoni+horizoncpupos1*N1-N1BND);
530  //}
531 
532  enerregiondef[POINTUP][1]=totalsize[1]-1;
533  enerregiondef[POINTDOWN][2]=0;
534  enerregiondef[POINTUP][2]=totalsize[2]-1;
535  enerregiondef[POINTDOWN][3]=0;
536  enerregiondef[POINTUP][3]=totalsize[3]-1;
537 
538  return(0);
539 }
540 
541 
542 
543 
544 
545 // enerregion for jet parts of grid
546 // determines the flux positions for each CPU for the jet region (jetedge) AND the range of volume integration for cons. variables in jet (jetpos).
547 // ISSUEMARK: the below only works for a grid with full Pi. Crashes code at runtime otherwise! should fix.
548 // ISSUEMARK: assume this is an intrinsically axisymmetric function, so k (\phi) is just carried along -- no truncation in \phi
549 int setjetflux(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
550 {
551  FTYPE X[NDIM],V[NDIM],r,th;
552  int i,j,k,pl,pliter;
553  int dir;
554  FTYPE startth,endth,thetajet;
555  int jetedge[NUMJETS];
556  int doprintout;
557 
558 
559  doprintout=(!specialstep && initialcall==1);
560 
561  if(defcoord==EQMIRROR){
562  dualfprintf(fail_file,"setjetflux() not setup to work for non-full-Pi grids\n");
563  myexit(1);
564  }
565 
566 
567  // jet region is assumed to be within a constant theta slice
568  // this is theta w.r.t. polar axis
569  thetajet=M_PI*0.5-h_over_r_jet;
570  // find j for which theta is at our prespecified point
571 
572  i=0;j=0;k=0;
573  bl_coord_coord(i, j, k, FACE2, X, V);
574  startth=V[2];
575  i=0;j=N2;k=0;
576  bl_coord_coord(i, j, k, FACE2, X, V);
577  endth=V[2];
578 
579  // assumes 0<thetajet<Pi/2
580  if((fabs(startth-thetajet)/thetajet<1E-8)||
581  (fabs(endth-thetajet)/thetajet<1E-8)||
582  (fabs(startth-(M_PI-thetajet))/thetajet<1E-8)||
583  (fabs(endth-(M_PI-thetajet))/thetajet<1E-8)
584  ){
585  dualfprintf(fail_file,"thetajet is on top of grid, move h_over_r_jet a bit\n");
586  myexit(1);
587  }
588 
589 
591  //
592  // INNERJET
593  //
594 
595  // setup pointers
598 
599 
600  // see if jet edge is related to this CPU
601  // assumes increasing j is increasing th
602  if((startth<=thetajet)&&(endth<=thetajet)){
603  // if cpu entirely within inner theta jet
604  enerpos[X1DN]=0;
605  enerpos[X1UP]=N1-1;
606  enerpos[X2DN]=0;
607  enerpos[X2UP]=N2-1;
608  enerpos[X3DN]=0;
609  enerpos[X3UP]=N3-1;
610  jetedge[INNERJET]=FLUXNOTONGRID;
611  }
612  else if((startth<thetajet)&&(endth>thetajet)){
613  // if inner jet edge is on this CPU but not on boundary
614  enerpos[X1DN]=0;
615  enerpos[X1UP]=N1-1;
616  enerpos[X2DN]=0;
617 
618  // default:
619  enerpos[X2UP]=0;
620  jetedge[INNERJET]=FLUXNOTONGRID;
621 
622  i=0;
623  for(j=0;j<=OUTM2;j++){
624  bl_coord_coord(i, j, k, FACE2, X, V);
625  r=V[1];
626  th=V[2];
627  // look for switch from below to above thetajet at inner theta jet edge
628  if(th>thetajet){
629  enerpos[X2UP]=jm1mac(j);
630  jetedge[INNERJET]=j;
631  break;
632  }
633  }
634  enerpos[X3DN]=0;
635  enerpos[X3UP]=N3-1;
636  }
637  else if((startth>=thetajet)&&(endth>=thetajet)){
638  // if cpu is entirely not contained in inner jet
645  jetedge[INNERJET]=FLUXNOTONGRID;
646  }
647  else{
648  trifprintf("problem with INNERJET setjetflux()\n");
649  myexit(1);
650  }
651 
652 
653 
654  // left edge (any directional condition would do)
655  if((N1>1)&&(enerpos[X1DN]!=FLUXNOTONGRID)&&(mycpupos[1]==0)){
656  doflux[X1DN]=0; // or horizoni
657  if(doprintout) trifprintf("proc: %d doing inner jet flux X1DN\n",myid);
658  }
659  else doflux[X1DN]=FLUXNOTONGRID;
660 
661  // right edge (any directional condition would do)
662  if((N1>1)&&(enerpos[X1UP]!=FLUXNOTONGRID)&&(mycpupos[1]==ncpux1-1)){
663  doflux[X1UP]=OUTM1;
664  if(doprintout) trifprintf("proc: %d doing inner jet flux X1UP\n",myid);
665  }
666  else doflux[X1UP]=FLUXNOTONGRID;
667 
668  // lower theta boundary
669  if((N2>1)&&(enerpos[X2DN]!=FLUXNOTONGRID)&&(mycpupos[2]==0)){
670  doflux[X2DN]=0;
671  if(doprintout) trifprintf("proc: %d doing inner jet flux X2DN\n",myid);
672  }
673  else doflux[X2DN]=FLUXNOTONGRID;
674 
675  // upper theta boundary
676  if((N2>1)&&(enerpos[X2UP]!=FLUXNOTONGRID)&&(jetedge[INNERJET]!=FLUXNOTONGRID)){ // only get flux if CPU has edge
677  doflux[X2UP]=jetedge[INNERJET];
678  if(doprintout) trifprintf("proc: %d doing inner jet flux X2UP\n",myid);
679  }
680  else doflux[X2UP]=FLUXNOTONGRID;
681 
682  if((N3>1)&&(enerpos[X3DN]!=FLUXNOTONGRID)&&(mycpupos[3]==0)){
683  doflux[X3DN]=0;
684  if(doprintout) trifprintf("proc: %d doing inner jet flux X3DN\n",myid);
685  }
686  else doflux[X3DN]=FLUXNOTONGRID;
687 
688  // right edge (any directional condition would do)
689  if((N3>1)&&(enerpos[X3UP]!=FLUXNOTONGRID)&&(mycpupos[3]==ncpux3-1)){
690  doflux[X3UP]=OUTM3;
691  if(doprintout) trifprintf("proc: %d doing inner jet flux X3UP\n",myid);
692  }
693  else doflux[X3UP]=FLUXNOTONGRID;
694 
695 
696  if(doprintout) {
697  DIRLOOP(dir) trifprintf("proc: %d %d innerjet: doflux[%d]=%d enerpos[%d]=%d\n",myid,INNERJETREGION,dir,doflux[dir],dir,enerpos[dir]);
698  }
699 
701  //
702  // OUTERJET
703  //
704 
705  // setup pointers
707  doflux=dofluxreg[OUTERJETREGION];
708 
709 
710  // see if outer jet edge is related to this CPU
711  if((startth<=M_PI-thetajet)&&(endth<=M_PI-thetajet)){
712  // if cpu entirely not within outer jet region
719  jetedge[OUTERJET]=FLUXNOTONGRID;
720  }
721  else if((startth<M_PI-thetajet)&&(endth>M_PI-thetajet)){
722  enerpos[X1DN]=0;
723  enerpos[X1UP]=N1-1;
724 
725  // default:
726  enerpos[X2DN]=0;
727  jetedge[OUTERJET]=FLUXNOTONGRID;
728  // if outer jet edge is on this CPU but not on boundary
729  i=0;k=0;
730  for(j=0;j<=OUTM2;j++){
731  bl_coord_coord(i, j, k, FACE2, X, V);
732  th=V[2];
733  // look for switch from below to above thetajet at inner theta jet edge
734  if(th>M_PI-thetajet){
735  enerpos[X2DN]=jm1mac(j);
736  jetedge[OUTERJET]=jm1mac(j);
737  break;
738  }
739  }
740  enerpos[X2UP]=N2-1;
741 
742  enerpos[X3DN]=0;
743  enerpos[X3UP]=N3-1;
744 
745  // dualfprintf(fail_file,"HIT2: %d %d %d %d %d %d\n",enerpos[X1DN],enerpos[X1UP],enerpos[X2DN],enerpos[X2UP],enerpos[X3DN],enerpos[X3UP]);
746  }
747  else if((startth>=M_PI-thetajet)&&(endth>=M_PI-thetajet)){
748  // if cpu is entirely containe within outer jet
749  enerpos[X1DN]=0;
750  enerpos[X1UP]=N1-1;
751  enerpos[X2DN]=0;
752  enerpos[X2UP]=N2-1;
753  enerpos[X3DN]=0;
754  enerpos[X3UP]=N3-1;
755  jetedge[OUTERJET]=FLUXNOTONGRID;
756  }
757  else{
758  trifprintf("problem with OUTERJET setjetflux()\n");
759  myexit(1);
760  }
761 
762  if((N1>1)&&(enerpos[X1DN]!=FLUXNOTONGRID)&&(mycpupos[1]==0)){
763  doflux[X1DN]=0; // or horizoni
764  if(doprintout) trifprintf("proc: %d doing outer jet flux X1DN\n",myid);
765  }
766  else doflux[X1DN]=FLUXNOTONGRID;
767 
768  if((N1>1)&&(enerpos[X1UP]!=FLUXNOTONGRID)&&(mycpupos[1]==ncpux1-1)){
769  doflux[X1UP]=OUTM1;
770  if(doprintout) trifprintf("proc: %d doing outer jet flux X1UP\n",myid);
771  }
772  else doflux[X1UP]=FLUXNOTONGRID;
773 
774  if((N2>1)&&(enerpos[X2DN]!=FLUXNOTONGRID)&&(jetedge[OUTERJET]!=FLUXNOTONGRID)){
775  doflux[X2DN]=jetedge[OUTERJET];
776  if(doprintout) trifprintf("proc: %d doing outer jet flux X2DN\n",myid);
777  }
778  else doflux[X2DN]=FLUXNOTONGRID;
779 
780  if((N2>1)&&(enerpos[X2UP]!=FLUXNOTONGRID)&&(mycpupos[2]==ncpux2-1)){
781  doflux[X2UP]=OUTM2;
782  if(doprintout) trifprintf("proc: %d doing outer jet flux X2UP\n",myid);
783  }
784  else doflux[X2UP]=FLUXNOTONGRID;
785  // fluxes are on edges of zone, so 0 and N are on edge fluxes
786 
787  if((N3>1)&&(enerpos[X3DN]!=FLUXNOTONGRID)&&(mycpupos[3]==0)){
788  doflux[X3DN]=0;
789  if(doprintout) trifprintf("proc: %d doing outer jet flux X3DN\n",myid);
790  }
791  else doflux[X3DN]=FLUXNOTONGRID;
792 
793  if((N3>1)&&(enerpos[X3UP]!=FLUXNOTONGRID)&&(mycpupos[3]==ncpux3-1)){
794  doflux[X3UP]=OUTM3;
795  if(doprintout) trifprintf("proc: %d doing outer jet flux X3UP\n",myid);
796  }
797  else doflux[X3UP]=FLUXNOTONGRID;
798 
799 
800  if(1||doprintout){
801  DIRLOOP(dir) trifprintf("proc: %d %d outerjet: doflux[%d]=%d enerpos[%d]=%d\n",myid,OUTERJETREGION,dir,doflux[dir],dir,enerpos[dir]);
802  }
803 
804  return(0);
805 }