HARM
harm and utilities
 All Data Structures Files Functions Variables Typedefs Macros Pages
initbase.gridsectioning.c
Go to the documentation of this file.
1 
12 #include "decs.h"
13 
14 
15 
16 
17 
18 
19 
20 static int check_limitsinbox(FTYPE rlo, FTYPE rhi, int iloabs, int ihiabs, int doreport);
21 
22 
26 int setgridsectioning(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
27 {
28 
29  if(DOGRIDSECTIONING==0){
30  dualfprintf(fail_file,"Shouldn't be here in setgridsectioning() with DOGRIDSECTIONING=%d\n",DOGRIDSECTIONING);
31  myexit(3139686);
32  }
33 
34  if(initialcall==1){
35  // force update to ACTIVEREGION
36  // initialize grid sectioning to full grid at first
37  init_gridsectioning();
38  }
39  else{
40  findandsetactivesection(initialcall, timeorder, numtimeorders, thenstep, thetime );
41  }
42 
43  return(0);
44 }
45 
46 
47 
52 int init_gridsectioning(void)
53 {
54  int doprintout;
55  int dimen;
56  int badglobal_sectiondef;
57  int faketimeorder,fakenumtimeorders;
58 
59 
60 
61 
62 
63  if( DOGRIDSECTIONING ){
64  trifprintf("Initializing grid sectioning: BEGIN\n");
65 
66  faketimeorder=-1;
67  fakenumtimeorders=-1;
68 
69  if( RESTARTMODE == 0 ) {
70  findandsetactivesection(1,faketimeorder,fakenumtimeorders,nstep, t ); //SASMARK SECTIONMARK
71  }
72  else {
73  //set up active section arrays either by using read-in parameters of the active section OR, if this
74  //info is absent from restart file, from the current time
75  doprintout = 1;
76  badglobal_sectiondef=0;
77  DIMENLOOP(dimen){
78  if(global_enerregiondef[ACTIVEREGION][POINTDOWN][dimen] < - MAXBND || global_enerregiondef[ACTIVEREGION][POINTUP][dimen] > totalsize[dimen] + MAXBND-1 || global_enerregiondef[ACTIVEREGION][POINTDOWN][dimen] >= global_enerregiondef[ACTIVEREGION][POINTUP][dimen]){
79  badglobal_sectiondef=1;
80  }
81  }
82  if(badglobal_sectiondef){
83  trifprintf( "Sectioning info mangled; regenerating it for current time t = %21.15g\n", t );
84  findandsetactivesection(1,faketimeorder,fakenumtimeorders,nstep, t );
85  }
86  else {
87  setactivesection( global_enerregiondef[ACTIVEREGION], doprintout );
88  }
89  }
90  trifprintf("Initializing grid sectioning: END\n");
91  }
92 
93 
94 
95  return(0);
96 }
97 
98 
105 int bound_gridsectioning(int primtype, FTYPE (*prim)[NSTORE2][NSTORE3][NPR], FTYPE (*pstag)[NSTORE2][NSTORE3][NPR], FTYPE (*ucons)[NSTORE2][NSTORE3][NPR], int finalstep)
106 {
107  FTYPE (*primsource)[NSTORE2][NSTORE3][NPR];
108  FTYPE (*primdest)[NSTORE2][NSTORE3][NPR];
109  int i,j,k,pl,pliter;
110  int dimen;
111  struct of_geom geomdontuse;
112  struct of_geom *ptrgeom=&geomdontuse;
113  struct of_state q;
114  FTYPE Unew[NPR];
115 
116 
117 
118 
119 
120  return(0); // no longer need to bound due to grid sectioning // carefully bound and iterate only those things needed with constrained loops.
121 
122 
123 
124  dualfprintf(fail_file,"Should not be in bound_gridsectioning EVER: deprecated code\n");
125  myexit(248967233);
126 
127 
128  if(DOGRIDSECTIONING==0){
129  dualfprintf(fail_file,"Should not be in bound_gridsectioning\n");
130  myexit(248967234);
131  }
132 
133  // global variables to point to in order to get defined primitives for intermediate RK primitives
134  // GLOBALMARK
135  if(primtype==CENTEREDPRIM){
136  primsource=GLOBALPOINT(pglobal);
137  primdest=prim;
138  }
139  else{
140  primsource=GLOBALPOINT(pstagglobal);
141  primdest=pstag;
142  }
143 
144 
145 
146 
147 
148  //only for grid sectioning: to fill in quasi-ghost zones (zones not already filled by bound() call)
149  if(primdest != primsource) {
150 
151  // Need to set real boundary conditions to something unless user uses WITHINACTIVESECTION(ri,rj,rk) inside their bounds.c
152  // This sets non-active region
153  if(primtype==STAGGEREDPRIM){
154  // Never reach here since only 1 version of pstag=pstagglobal for all RK substeps
155  FULLLOOP{
157  pl=B1; MACP0A1(primdest,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl); //SASMARK SECTIONING
158  }
160  pl=B2; MACP0A1(primdest,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl); //SASMARK SECTIONING
161  }
163  pl=B3; MACP0A1(primdest,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl); //SASMARK SECTIONING
164  }
165  if(!WITHINACTIVEWITHBNDSECTION(i,j,k)){
166  PLOOP(pliter,pl){
167  if(pl!=B1 && pl!=B2 && pl!=B3) MACP0A1(primdest,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl); //SASMARK SECTIONING
168  }
169  }
170  }
171  }
172  else{
173  FULLLOOP{
174  if(!WITHINACTIVEWITHBNDSECTION(i,j,k)){
175  PLOOP(pliter,pl) MACP0A1(primdest,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl); //SASMARK SECTIONING
176  }
177  }
178  }
179  }
180 
181 
182 
183  if(finalstep){
185  // GODMARK: not sure if below needed
186  if(FLUXB==FLUXCTSTAG || DOENOFLUX != NOENOFLUX ){
187  // then need to deal with unew
188  // force unew to be as prim (so second order)
189 
190  // Note that unlike primitive, conserved quantity is multi-positional so only one thing to modify
191 
192  if(FLUXB==FLUXCTSTAG && primtype==STAGGEREDPRIM){
193 
194  FULLLOOP{
196  dimen=1;
197  get_geometry(i, j, k, FACE1-1+dimen, ptrgeom);
198  pl=B1-1+dimen;
199  MACP0A1(ucons,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl)*(ptrgeom->EOMFUNCMAC(pl)); // UEVOLVE
200  }
202  dimen=2;
203  get_geometry(i, j, k, FACE1-1+dimen, ptrgeom);
204  pl=B1-1+dimen;
205  MACP0A1(ucons,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl)*(ptrgeom->EOMFUNCMAC(pl)); // UEVOLVE
206  }
208  dimen=3;
209  get_geometry(i, j, k, FACE1-1+dimen, ptrgeom);
210  pl=B1-1+dimen;
211  MACP0A1(ucons,i,j,k,pl) = MACP0A1(primsource,i,j,k,pl)*(ptrgeom->EOMFUNCMAC(pl)); // UEVOLVE
212  }
213  // no need to fill ucons[!=B1,B2,B3]
214  }
215  }// end if prim was staggered
216 
217  if(FLUXB==FLUXCTSTAG && primtype==CENTEREDPRIM){
218  // unew for field is not set
219  FULLLOOP{
220  if(!WITHINACTIVEWITHBNDSECTION(i,j,k)){
221  get_geometry(i, j, k, CENT, ptrgeom);
222  MYFUN(get_state(MAC(primsource,i,j,k), ptrgeom, &q),"step_ch.c:advance()", "get_state()", 1);
223  MYFUN(primtoU(UEVOLVE,MAC(primsource,i,j,k), &q, ptrgeom, Unew, NULL),"initbase.gridsectioning.c:bound_gridsectioning()", "primtoU()", 1);
224  PLOOPNOB1(pl) MACP0A1(ucons,i,j,k,pl)=Unew[pl];
225  PLOOPNOB2(pl) MACP0A1(ucons,i,j,k,pl)=Unew[pl];
226  }
227  }
228  }// end if prim was centered
229 
230  if(FLUXB!=FLUXCTSTAG && primtype==CENTEREDPRIM){
231  // unew for field is set
232  FULLLOOP{
233  if(!WITHINACTIVEWITHBNDSECTION(i,j,k)){
234  get_geometry(i, j, k, CENT, ptrgeom);
235  MYFUN(get_state(MAC(primsource,i,j,k), ptrgeom, &q),"step_ch.c:advance()", "get_state()", 1);
236  MYFUN(primtoU(UEVOLVE,MAC(primsource,i,j,k), &q, ptrgeom, Unew, NULL),"initbase.gridsectioning.c:bound_gridsectioning()", "primtoU()", 1);
237  PLOOP(pliter,pl) MACP0A1(ucons,i,j,k,pl)=Unew[pl];
238  }
239  }
240  }// end if prim was centered
241 
242  }
243  }// end if finalstep, upon which then only should change conserved quantity that (unew) that is summed over all RK substeps
244 
245  return(0);
246 
247 }
248 
249 
250 
260 int findindexfromradius(FTYPE xr, int *xcpupos1, int *xi)
261 {
262  int i, j, k, ii;
263  FTYPE r1, r2;
264  FTYPE X[NDIM],V[NDIM];
265  int gotit;
266  int fromwhere;
267 
268 
269  // need to find horizon and place horizoni on right-hand-side of location
270 
271  // definition of horizoni must be consistent so fluxes are consistent and have conservation
272  fromwhere=1; // force to be on upside unless Rhor=0, which is caught first
273 
274  // find cpu column that brackets the horizon and determine the
275  // i-offset of horizon
276  // notice that only 1 CPU will get horizon since stop process once found
277  // notice that radius(horizoni) is below or equal to actual horizon radius
278 
279 
280  *xi = FLUXNOTONGRID;
281  *xcpupos1 = -1;
282  gotit = 0;
283  for (ii = numprocs - 1; ii >= 0; ii--) { // should get done by first row
284  if (ii == myid) {
285  for (i = N1-1; i >= 0; i--) {
286  if( BCtype[X2UP] == POLARAXIS ) {
287  j = totalsize[2]-1-startpos[2]; //on the polar axis
288  k = totalsize[3]-1-startpos[3]; //on the polar axis
289  }
290  else if( BCtype[X2DN] == POLARAXIS ) {
291  j = 0-startpos[2]; //on the polar axis
292  k = 0-startpos[3]; //on the polar axis
293  }
294  else {
295  j = N2 / 2; // doesn't matter (spherical polar assumed)
296  k = N3 / 2; // doesn't matter (spherical polar assumed)
297  }
298  coord(i, j, k, FACE1, X);
299  bl_coord(X, V);
300  r1=V[1];
301  coord(ip1mac(i), j, k, FACE1, X);
302  bl_coord(X, V);
303  r2=V[1];
304  // looking between FACE1's r value and upper FACE1's r value, so loop is from i=N1-1..i=0
305 
306  if(ii==myid && myid==0 && i==0){ //radius to the left of the grid
307  // special check in case radius inside inner-most radial grid
308  if(xr<=r1){
309  // then horizon off grid or right on edge, but still ok
310  // treat as if horizon is off grid if right on edge
311  *xi = 0;
312  *xcpupos1=mycpupos[1];
313  break;
314  }
315  }
316 
317  if(ii==myid && myid==numprocs-1 && i==N1-1){ //radius to the right of the grid
318  // special check in case radius outside outer-most radial grid
319  if(xr>=r2){
320  // then radius off grid or right on edge, but still ok
321  // treat as if horizon is off grid if right on edge
322  // *xi = N1-1;
323  *xi = N1; // Become N1 so that code knows off grid from FACE
324  *xcpupos1=mycpupos[1];
325  break;
326  }
327  }
328 
329  if (fromwhere!=2){
330  if(xr >= r1 && xr < r2){ // note that if strictly on r2, then next CPU should pick it up
331  *xi = i;
332  *xcpupos1 = mycpupos[1];
333  break;
334  }
335  }
336  else if (fromwhere==2){
337  if(xr >= r1 && xr < r2){
338  *xi = ip1mac(i);
339  *xcpupos1 = mycpupos[1];
340  if(*xi>=N1){
341  *xi=0;
342  ++(*xcpupos1);
343  }
344  else{
345  // then on original CPU
346  *xcpupos1 = mycpupos[1];
347  }
348  break;
349  }
350  }
351  }
352  }
353 
354  if (numprocs > 0) {
355 #if(USEMPI)
356  MPI_Bcast(xi, 1, MPI_INT, MPIid[ii], MPI_COMM_GRMHD);
357  MPI_Bcast(xcpupos1, 1, MPI_INT, MPIid[ii], MPI_COMM_GRMHD);
358 #endif
359  }
360  if (*xi >= 0) gotit = 1; // can stop entire process
361 
362  // keep horizoni as relative to CPU with horizon so any CPU knows where horizon is
363  // if (mycpupos[1] != horizoncpupos1) {
364  // horizoni = FLUXNOTONGRID;
365  //} // reset if not right cpu group
366  if (gotit) break;
367  }
368 
369 
370 
371 
372  if(gotit==0){
373  dualfprintf(fail_file,"Never found grid cell corresponding to radius %21.15g : fromwhere=%d\n",xr,fromwhere);
374  myexit(6246);
375  }
376 
377 
379  //
380  // report some information
381 #if(PRODUCTION==0)
382  if(1||fromwhere==0) {
383  trifprintf("xi: %d xcpupos1: %d\n", *xi, *xcpupos1);
384  // just a check
385  dualfprintf(log_file,"xi: %d mycpupos[1]: %d xcpupos1: %d\n", *xi, mycpupos[1], *xcpupos1);
386 
387  trifprintf("end: find_horizon\n");
388  }
389 #endif
390 
391  return(0);
392 }
393 
394 
395 
402 int findandsetactivesection(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime )
403 {
404  int iloabs, ihiabs;
405  int jloabs, jhiabs;
406  int kloabs, khiabs;
407  int updateeverynumsteps;
408  int everynumsteps;
409  int doprintout,doset;
410  int sectiondef[NUMUPDOWN][NDIM];
411  static int firsttimerealgridset=1;
412 
413 
414 #if( DOGRIDSECTIONING == 0 )
415  dualfprintf(fail_file,"Got inside findandsetactivesection() with DOGRIDSECTIONING == 0\n");
416  myexit(246983462);
417 #endif
418 
419 
420 
421 #if(USEOPENMP)
422  if(omp_in_parallel()){
423  dualfprintf(fail_file,"setgeneral_enerregion() called in parallel region\n");
424  myexit(853736);
425  }
426 #endif
427 
428 
429  if(initialcall==1){
430  // this indicates very first setup call that should (in general) set full grid right now
431 
432  // nothing interesting to report for initialization since not even bl_coord() defined yet
433  doprintout = 0;
434 
435  // normal full total grid
436  sectiondef[POINTDOWN][1]=0;
437  sectiondef[POINTUP][1]=totalsize[1]-1;
438  sectiondef[POINTDOWN][2]=0;
439  sectiondef[POINTUP][2]=totalsize[2]-1;
440  sectiondef[POINTDOWN][3]=0;
441  sectiondef[POINTUP][3]=totalsize[3]-1;
442 
443  // compute numcompzones
445 
446  setactivesection( sectiondef, doprintout );
447 
448  return(0); // done!!
449  }
450 
451 
452 
454  //
455  // Update period choices
456  //
458 
459  // PROBLEM DEPENDENT FUNCTION:
460  theproblem_set_enerregionupdate(initialcall, timeorder, numtimeorders, thenstep, thetime, &updateeverynumsteps, &everynumsteps);
461 
462  // see if time for update
463  doset = (initialcall==-1 || (nstep % updateeverynumsteps==0) && (timeorder==numtimeorders-1) );
464  if(!doset) return(0); // nothing to do
465 
466  // see if should print out section information
467  // print out if first time in the real setting section (here)
468  doprintout = (nstep % everynumsteps==0) && (timeorder==numtimeorders-1) || (firsttimerealgridset==1);
469  firsttimerealgridset=0;
470 
472  //
473  // BELOW CALL's PROBLEM DEPENDENT FUNCTION for setting indices of active grid
474  //
476 
477  // Below function should exist in user's init.c that can call existing functions
478  theproblem_set_enerregiondef(initialcall, timeorder, numtimeorders, thenstep, thetime, sectiondef);
479 
480 
482  //
483  // Set active region (block shape in i,j,k)
484  //
486 
487 
488 
489  setactivesection( sectiondef, doprintout );
490 
491  // compute numcompzones
493 
494 
495  return( 0 );
496 }
497 
498 
499 int compute_numcompzones(int (*sectiondef)[NDIM], long long int *localnumcompzones)
500 {
501 
502  *localnumcompzones=(long long int)(sectiondef[POINTUP][1]-sectiondef[POINTDOWN][1]+1)*(long long int)(sectiondef[POINTUP][2]-sectiondef[POINTDOWN][2]+1)*(long long int)(sectiondef[POINTUP][3]-sectiondef[POINTDOWN][3]+1);
503 
504  return(0);
505 }
506 
507 
508 
509 
512 int setactivesection(int (*sectiondef)[NDIM], int doprintout)
513 {
514  int dimen;
515  int updowniter;
516 
517 
519  //
520  // Check hi/lo indicies
521  //
523  assert( DOGRIDSECTIONING != 1, "setactivesection(): grid sectioning should be enabled\n" );
524  DIMENLOOP(dimen){
525  assert( sectiondef[POINTDOWN][dimen] >= sectiondef[POINTUP][dimen], "setactivesection(): hi/lo indices out of order: dimen=%d losectiondef = %d, hisectiondef = %d\n", dimen, sectiondef[POINTDOWN][dimen], sectiondef[POINTUP][dimen] );
526  }
527 
528  // get region and its additional boundary region
529  setgeneral_enerregion(sectiondef, doprintout, ACTIVEREGION, ACTIVEWITHBNDREGION);
530 
531 
532  return( 0 );
533 }
534 
535 
536 
537 
538 
539 
540 
541 
542 
543 
544 
545 
551 
552 
553 
554 
557 int setsashawind_set_enerregiondef(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int (*enerregiondef)[NDIM] )
558 {
559  int cpupos1lo,cpupos1hi;
560  int ilo,ihi;
561  int iloabs,ihiabs;
562  FTYPE rlo,rhi;
563  int findindexfromradius(FTYPE xr, int *xcpupos1, int *xi);
564  int extra_safe_cells;
565  FTYPE t0,t1;
566 
567 
568 
569  extra_safe_cells = MAXBND;
570  t_transition_in=1; // was in bounds.c
571 
572  // Sasha's Wind
573  rlo = 0.02 * MAX(0,thetime - t_transition_in); //SASMARK SECTIONMARK -- hardcoded value of mm (or v^p)
574  //this may cause problems if the actual grid inner radius is smaller than 0.1
575  if( rlo < 0.1 ) {
576  rlo = 0.1;
577  }
578 
579  //discrete changes in lower radius of active section
580  //rlo = pow( 2., floor(log(rlo)/M_LN2l) );
581 
582  rhi = 3. * thetime + 3. * (2 * M_PI / 0.25); //SASMARK SECTIONMARK -- hardcoded value of mm (or v^p)
583  if( rhi > Rout ) {
584  rhi = Rout;
585  }
586 
587  //rlo = Rin;
588  rhi = Rout; //on bg don't care where the outer boundary is
589 
590  //X1DN boundary of active region
591  findindexfromradius( rlo, &cpupos1lo, &ilo );
592 
593  //X1UP boundary of active region
594  findindexfromradius( rhi, &cpupos1hi, &ihi );
595 
596  //find absolute index of the X1DN boundary
597  iloabs = cpupos1lo * N1 + ilo;
598 
599  //find absolute index of the X1UP boundary
600  ihiabs = cpupos1hi * N1 + ihi;
601 
602  //add extra cells for safety to ensure shock does not come too close numerically
603  //to the X1UP boundary
604  ihiabs += extra_safe_cells;
605 
606  //make sure the X1UP boundary is on the grid
607  if( ihiabs >= totalsize[1] ) {
608  ihiabs = totalsize[1] - 1;
609  }
610 
611 
612  // problem Sasha refers to is boundary conditions set worse than on-grid set and kink and behavior at true boundary leads to wave going back
613  ihiabs = (totalsize[1] - 1) - MAXBND; //to avoid problems at the upper boundary
614 
615  //iloabs = MAX( iloabs, ihiabs - totalsize[1]/2 ); //don't care for BG (was done on mako so that no more than half grid is in active section)
616 
617 
618  enerregiondef[POINTDOWN][1]=iloabs;
619  enerregiondef[POINTUP][1]=ihiabs;
620  enerregiondef[POINTDOWN][2]=0;
621  enerregiondef[POINTUP][2]=totalsize[2]-1;
622  enerregiondef[POINTDOWN][3]=0;
623  enerregiondef[POINTUP][3]=totalsize[3]-1;
624 
625 
626  return(0);
627 }
628 
629 
630 
632 int sashawind_set_enerregionupdate(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int *updateeverynumsteps, int *everynumsteps)
633 {
634 
636  //
637  // Setup update period
638  //
640  *updateeverynumsteps=100;
641  //number of steps after which position/size of active section is updated
642  *everynumsteps = *updateeverynumsteps;
643 
644  return(0);
645 }
646 
647 
648 
651 int torus_set_enerregiondef(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int (*enerregiondef)[NDIM] )
652 {
653  int cpupos1lo,cpupos1hi;
654  int ilo,ihi;
655  int iloabs,ihiabs;
656  FTYPE rlo,rhi;
657  int findindexfromradius(FTYPE xr, int *xcpupos1, int *xi);
658  int extra_safe_cells;
659  FTYPE t0,t1;
660 
661 
662 
663  // see advance.c: Whether to allow shift in evolved quantities to preserve conservation and divb=0. Set to zero if exposing that surface in time. Set to 1 if absorbing that surface in time and relying on it to inject a solution.
671 
672 
673  extra_safe_cells = MAXBND;
674 
675  // then switch to 6..Rout for active section with decreasing to original at late time
676  t0=50;
677  t1=150;
678  rlo = MAX(Rin-SMALL,6.0*MIN(1.0,1.0-(thetime-t0)/(t1-t0)));
679 
680 
681 
682  //rlo = Rin;
683  rhi = Rout; //on bg don't care where the outer boundary is
684 
685  //X1DN boundary of active region
686  findindexfromradius( rlo, &cpupos1lo, &ilo );
687 
688  //X1UP boundary of active region
689  findindexfromradius( rhi, &cpupos1hi, &ihi );
690 
691  //find absolute index of the X1DN boundary
692  iloabs = cpupos1lo * N1 + ilo;
693 
694  //find absolute index of the X1UP boundary
695  ihiabs = cpupos1hi * N1 + ihi;
696 
697  //add extra cells for safety to ensure shock does not come too close numerically
698  //to the X1UP boundary
699  ihiabs += extra_safe_cells;
700 
701  //make sure the X1UP boundary is on the grid
702  if( ihiabs >= totalsize[1] ) {
703  ihiabs = totalsize[1] - 1;
704  }
705 
706 
707  enerregiondef[POINTDOWN][1]=iloabs;
708  enerregiondef[POINTUP][1]=ihiabs;
709  enerregiondef[POINTDOWN][2]=0;
710  enerregiondef[POINTUP][2]=totalsize[2]-1;
711  enerregiondef[POINTDOWN][3]=0;
712  enerregiondef[POINTUP][3]=totalsize[3]-1;
713 
714 
715  return(0);
716 
717 }
718 
719 
720 
721 
724 int jet_set_enerregiondef(int initialcall, int timeorder, int numtimeorders, long int thenstep, FTYPE thetime, int (*enerregiondef)[NDIM] )
725 {
726  int cpupos1lo,cpupos1hi;
727  int ilo,ihi;
728  int iloabs,ihiabs;
729  FTYPE rlo,rhi;
730  int findindexfromradius(FTYPE xr, int *xcpupos1, int *xi);
731  int extra_safe_cells;
732  FTYPE t0,t1;
733  FTYPE velgrid;
734  int pl,pliter;
735  int i,j,k;
736  FTYPE newDTref,ftemp;
737  FTYPE Rint0,Routt0;
738  int reportbox;
739 
740 
741 
742 
743 
744 #if(0)
745  // DEBUG:
746  enerregiondef[POINTDOWN][1]=0;
747  enerregiondef[POINTUP][1]=88;
748 
749  enerregiondef[POINTDOWN][2]=0;
750  enerregiondef[POINTUP][2]=totalsize[2]-1;
751  enerregiondef[POINTDOWN][3]=0;
752  enerregiondef[POINTUP][3]=totalsize[3]-1;
753  return(0);
754 #endif
755 
756 
757 
758 
759  // see advance.c: Whether to allow shift in evolved quantities to preserve conservation and divb=0. Set to zero if exposing that surface in time. Set to 1 if absorbing that surface in time and relying on it to inject a solution.
760  // We don't preserve divb inside boundary being absorbed since missing inside-boundary EMF could have cancelled active emf at edge of grid leading to very different (say) B2 just inside boundary that determines inside-boundary divb value.
768 
769 
770 
771 
772 
773 
774 
775 
776  // setup
777  extra_safe_cells = MAXBND;
778  t_transition_in=5E3;
779  t_transition_out=1.0; // start moving almost immediately
780  Rint0=Rin*0.99;
781  Routt0=200.0;
782 
783 
784 
786  //
787  // X1UP
788  //
790  if(thetime<t_transition_out){
791 
792  rhi=Routt0;
793 
794  // have to always fix or at least always set EMF's to zero so divb stays zero when exposing solution
795  // BCtype[X1UP]=OUTFLOW;
796 
797  }
798  else{
799  velgrid=1.1; // move slight faster than speed of light so that relativistic flow doesn't ram into outer partially reflecting wall
800  rhi = Routt0 + velgrid*MAX(0,thetime - t_transition_out);
801 
802  // GODMARK: If were to change rhi (Rout), worry about exposing monopoles. Is this taken care of?
803 
804  }
805 
806 
807  // rhi = Rout; //on bg don't care where the outer boundary is
808 
809 
811  //
812  // X1DN -- controls dumping too
813  //
815  if(thetime<t_transition_in){
816  rlo=Rint0; // ensure gets ilo=0
817 
818  // CHANGINGMARK:
819  ftemp=50.0;
820  // ftemp=5.0;
821 
822  int idt;
823  for(idt=0;idt<NUMDUMPTYPES;idt++) DTdumpgen[idt]=ftemp;
829 
831 
832  }
833  else{
834 
835  // Can just set newDTref=thetime since diagnostics pre-determine next dump time at each dump rather than at every moment, but the above is more robust and keeps simpler times for dumps
836  // CHANGINGMARK:
837  ftemp=50.0;
838  //ftemp=5.0;
839 
840 
841 
842  velgrid=0.2;
843  rlo = Rint0 + Routt0 + velgrid*MAX(0,thetime - t_transition_in);
844 
845  //rlo = Rin;
846 
847 
848  //discrete changes in lower radius of active section
849  //rlo = pow( 2., floor(log(rlo)/M_LN2l) );
850 
851  // steps DT in powers of 10X
852  // newDTref = MAX(thetime,pow((int)log10(fabs(thetime)),10.0));
853 
854  // newDTref = DTdumpgen[MAINDUMPTYPE]*10.0;
855 
856  newDTref = round(rlo*ftemp);
857 
858 
865 
866  // change to free outflow? Allows inflow and outflow. Always extrapolates.
867  // BCtype[X1DN]=FREEOUTFLOW;
868  }
869 
870 
871 
872 
874  //
875  // Get global index from global positions
876  //
878 
879 
880  //X1DN boundary of active region
881  findindexfromradius( rlo, &cpupos1lo, &ilo );
882 
883 
884  //X1UP boundary of active region
885  findindexfromradius( rhi, &cpupos1hi, &ihi );
886 
887 
888  //find absolute index of the X1DN boundary
889  iloabs = cpupos1lo * N1 + ilo;
890 
891 
892  //find absolute index of the X1UP boundary
893  ihiabs = cpupos1hi * N1 + ihi;
894 
895 
896 
898  //
899  // check box limits
900  //
902  reportbox=1;
903  if(check_limitsinbox(rlo, rhi, iloabs,ihiabs,reportbox)){
905  // Then need to end computation
906  //
907  // equivalent to reaching final time
908  t=tf;// force to end
909  }
910  else{
912  //
913  // then still doing computation
914 
915  //add extra cells for safety to ensure shock does not come too close numerically
916  //to the X1UP boundary
917  // ihiabs += extra_safe_cells;
918 
919  //make sure the X1UP boundary is on the grid
920  if( ihiabs >= totalsize[1] ) {
921  ihiabs = totalsize[1] - 1;
922  }
923 
925  //
926  // Enforce relationship between ilo and ihi so that minimum number of cells operated on regardless of how (say) slow outer boundary moves
927  //
929  // Don't use for now, not necessarily needed if smart enough about moving those boundaries
930  // ihiabs = MAX(iloabs+MINGRIDSECTIONCELLSX1,ihiabs);
931 
932  if(thetime<t_transition_in){
933  iloabs=0; // enforce
934  // SUPERGODMARK: inconsistent with setting of horizon and how that affects computations?
935  }
936  }
937 
938 
940  //
941  // Set final section/region limits in terms of global index
942  //
944  enerregiondef[POINTDOWN][1]=iloabs;
945  enerregiondef[POINTUP][1]=ihiabs;
946  enerregiondef[POINTDOWN][2]=0;
947  enerregiondef[POINTUP][2]=totalsize[2]-1;
948  enerregiondef[POINTDOWN][3]=0;
949  enerregiondef[POINTUP][3]=totalsize[3]-1;
950 
951 
952  return(0);
953 
954 }
955 
956 
957 
958 
959 
960 
962 int check_limitsinbox(FTYPE rlo, FTYPE rhi, int iloabs, int ihiabs, int doreport)
963 {
964 
965 
966  if(iloabs>=totalsize[1]){
967  // >= , since checking if "radius" was within faces. Then if i=totalsize[1], then beyond last face
968  if(doreport) trifprintf("Lower grid section moved beyond outer box face\n");
969  return(1);
970  }
971 
972  if(ihiabs<0){
973  // <0 since ==0 is between face at 0 and 1
974  if(doreport) trifprintf("Upper grid section moved inside inner box face\n");
975  return(1);
976  }
977 
978  if(iloabs>ihiabs){
979  // can be equal, but not beyond eachother
980  // when equal, plausible that "radius" sits between both faces so need to compute that single cell
981  // need to check "radius" itself to ensure radii haven't moved beyond eachother
982  if(doreport) trifprintf("Lower grid section moved beyond upper grid section\n");
983  return(1);
984  }
985 
986  if(rlo>=rhi){
987  // then no region to compute
988  if(doreport) trifprintf("Lower radius of grid section moved beyond radius of upper grid section\n");
989  return(1);
990  }
991 
992 
993  // if reached here, then ok to continue computing
994  return(0);
995 }
996 
997 
998 
999 
1000 
1001 
1002 
1003 
1004 
1005 
1006 
1007 
1008 
1011 int jet_set_myid(void)
1012 {
1013 
1014  if(USEMPI==0){
1015  return(0); // nothing to do ever
1016  }
1017 
1018  if(DOGRIDSECTIONING==0){
1019  return(0); // nothing to do so far as I can tell
1020  }
1021  else{
1022 
1023  // Can choose to rearrange MPI tasks
1024 
1025  // Assume TACC Ranger affinity order for MPI tasks by rank.
1026  // http://services.tacc.utexas.edu/index.php/ranger-user-guide
1027 
1028  // Assume we use "8way" option on Ranger so that tasks are originally:
1029  // rank0 -> Socket0
1030  // rank1 -> Socket0
1031  // rank2 -> Socket1
1032  // rank3 -> Socket1
1033  // rank4 -> Socket2
1034  // rank5 -> Socket2
1035  // rank6 -> Socket3
1036  // rank7 -> Socket4
1037 
1038  // We want ranks ordered such that upper-half of physical grid has even ranks and lower half has odd ranks.
1039 
1040  // reorder MPI ranks so that each socket has 2 MPI tasks
1041 
1042 
1043  int ranki,rankj,rankk,origid,newid;
1044  for(rankk=0;rankk<ncpux3;rankk++){
1045  for(rankj=0;rankj<ncpux2;rankj++){
1046  for(ranki=0;ranki<ncpux1;ranki++){
1047  origid=ranki + rankj*ncpux1 + rankk*ncpux1*ncpux2;
1048  if(ranki<ncpux1/2){
1049  newid=ranki + rankj*(ncpux1/2) + rankk*(ncpux1/2)*ncpux2;
1050  // converts 0,1,2,3,4,... -> 0,2,4,6,8,...
1051  MPIid[origid]=newid*2;
1052  }
1053  else if(ranki>=ncpux1/2){
1054  newid=(ranki-ncpux1/2) + rankj*(ncpux1/2) + rankk*(ncpux1/2)*ncpux2;
1055  // converts 0,1,2,3,4,... -> 1,3,5,7,9,...
1056  MPIid[origid]=newid*2+1;
1057  }
1058  }
1059  }
1060  }// end over rankk
1061 
1062 
1063  // Note that unlike TACC Ranger, TACC Lonestar has 2 sockets with 2 cores per socket, but sockets *share* main memory. So no special socket association is required for optimal memory use.
1064  // http://services.tacc.utexas.edu/index.php/lonestar-user-guide
1065 
1066 
1067 
1068  }
1069 
1070 
1071 
1072  return(0);
1073 }