PLUTO
sb_tools.c File Reference

Miscellaneous functions for implementing the shearing-box boundary condition. More...

#include "pluto.h"
Include dependency graph for sb_tools.c:

Go to the source code of this file.

Functions

void SB_SetBoundaryVar (double ***U, RBox *box, int side, double t, Grid *grid)
 
void SB_FillBoundaryGhost (double ***U, RBox *box, int nghL, int nghR, Grid *grid)
 
void SB_ShearingInterp (double *qL, double *qR, double t, int side, Grid *grid)
 
int SB_JSHIFT (int jc)
 

Variables

static double sb_Ly
 

Detailed Description

Miscellaneous functions for implementing the shearing-box boundary condition.

The shearing-box tool file contains various functions for the implementation of the shearingbox boundary conditions in serial or parallel mode. The SB_SetBoundaryVar() function applies shearing-box boundary conditions to a 3D array U[k][j][i] at an X1_BEG or X1_END boundary. The array U[k][j][i] is defined on the RBox *box with grid indices (box->ib) <= i <= (box->ie), (box->jb) <= j <= (box->je) (box->kb) <= k <= (box->ke), and assumes that periodic boundary conditions have already been set. Indices in the y-directions are not necessary, since the entire y-range is assumed.

In parallel mode, we use the SB_ShiftBoundaryVar() function to perform the integer shift of cells across the processors, while interpolation function SB_ShearingInterp() handles the fractional part only. In serial or when there's only 1 processor along y, the interpolation function does all the job (integer+fractional).

Authors
A. Mignone (migno.nosp@m.ne@p.nosp@m.h.uni.nosp@m.to.i.nosp@m.t)
G. Muscianisi (g.mus.nosp@m.ican.nosp@m.isi@c.nosp@m.inec.nosp@m.a.it)
Date
Jan 31, 2014

Definition in file sb_tools.c.

Function Documentation

void SB_FillBoundaryGhost ( double ***  U,
RBox box,
int  nghL,
int  nghR,
Grid grid 
)

Fill ghost zones in the Y direction in the X1_BEG and X1_END boundary regions.

Parameters
[in,out]Ua 3D data array
[in,out]boxthe RBox structure containing the grid indices in the x and z directions. Indices in the y-directions are reset here for convenience.
[in]nghLnumber of ghost zones on the left
[in]nghRnumber of ghost zones on the right
[in]gridpointer to an
Note
nghL and nghR can be different for staggered fields like BY.
Returns
This function has no return value.

Definition at line 297 of file sb_tools.c.

314 {
315  int i, j, k;
316  int jb0, je0;
317  #ifdef PARALLEL
318  int coords[3];
319  long int count, buf_size;
320  static double *snd_buf1, *snd_buf2, *rcv_buf1, *rcv_buf2;
321  static int dst1, dst2;
322  static MPI_Comm cartcomm;
323  MPI_Status status;
324  #endif
325 
326 /* -------------------------------------------------------
327  save a copy of the original grid indices in the y-dir
328  ------------------------------------------------------- */
329 
330  jb0 = box->jb;
331  je0 = box->je;
332 
333 /* ------------------------------------------------------------------
334  impose periodic b.c. if there's only 1 processor along y
335  ------------------------------------------------------------------ */
336 
337  if (grid[JDIR].nproc == 1){
338  box->jb = JBEG - nghL;
339  box->je = JBEG - 1;
340  BOX_LOOP(box, k, j, i) U[k][j][i] = U[k][j + NX2][i];
341 
342  box->jb = JEND + 1;
343  box->je = JEND + nghR;
344  BOX_LOOP(box, k, j, i) U[k][j][i] = U[k][j - NX2][i];
345 
346  box->jb = jb0; box->je = je0;
347  return;
348  }
349 
350 #ifdef PARALLEL
351 
352 /* ----------------------------------------------------------------
353  - allocate memory for maximum buffer size;
354  - get destination ranks of the processors lying above and
355  below current processor.
356  This is done only once at the beginning since parallel
357  decomposition is not going to change during the computation.
358  ---------------------------------------------------------------- */
359 
360  if (snd_buf1 == NULL){
361 
362  i = grid[IDIR].nghost;
363  j = grid[JDIR].nghost;
364  k = NX3_TOT;
365  #ifdef STAGGERED_MHD
366  j++;
367  k++;
368  #endif
369  snd_buf1 = ARRAY_1D(i*j*k, double);
370  snd_buf2 = ARRAY_1D(i*j*k, double);
371  rcv_buf1 = ARRAY_1D(i*j*k, double);
372  rcv_buf2 = ARRAY_1D(i*j*k, double);
373 
374  AL_Get_cart_comm(SZ, &cartcomm);
375 
376  for (i = 0; i < DIMENSIONS; i++) coords[i] = grid[i].rank_coord;
377  coords[JDIR] -= 1;
378  MPI_Cart_rank(cartcomm, coords, &dst1);
379 
380  coords[JDIR] += 2;
381  MPI_Cart_rank(cartcomm, coords, &dst2);
382 
383  }
384 
385 /* -----------------------------------------------------------------
386  Send/receive buffers.
387  Buffer snd_buf1 is sent to rank [dst1] while snd_buf2 is sent
388  to rank [dst2] as follows:
389 
390 
391  |_____[dst1]_____| |________________| |_____[dst2]_____|
392  <---> <--->
393  <----- buf1 buf2 ---->
394  ----------------------------------------------------------------- */
395 
396 /* -- send buffer at JBEG -- */
397 
398  count = 0;
399  box->jb = JBEG;
400  box->je = JBEG + nghR - 1;
401  buf_size = (box->ke - box->kb + 1)
402  *(box->je - box->jb + 1)
403  *(box->ie - box->ib + 1);
404  BOX_LOOP(box, k, j, i) snd_buf1[count++] = U[k][j][i];
405 
406  MPI_Sendrecv(snd_buf1, buf_size, MPI_DOUBLE, dst1, 1,
407  rcv_buf2, buf_size, MPI_DOUBLE, dst2, 1,
408  cartcomm, &status);
409 
410 /* -- send buffer at JEND -- */
411 
412  count = 0;
413  box->jb = JEND - nghL + 1;
414  box->je = JEND;
415  buf_size = (box->ke - box->kb + 1)
416  *(box->je - box->jb + 1)
417  *(box->ie - box->ib + 1);
418  BOX_LOOP(box, k, j, i) snd_buf2[count++] = U[k][j][i];
419 
420  MPI_Sendrecv(snd_buf2, buf_size, MPI_DOUBLE, dst2, 2,
421  rcv_buf1, buf_size, MPI_DOUBLE, dst1, 2,
422  cartcomm, &status);
423 
424 /* -- place buffers in the correct position -- */
425 
426  count = 0;
427  box->jb = JEND + 1;
428  box->je = JEND + nghR;
429  BOX_LOOP(box, k, j, i) U[k][j][i] = rcv_buf2[count++];
430 
431  count = 0;
432  box->jb = JBEG - nghL;
433  box->je = JBEG - 1;
434  BOX_LOOP(box, k, j, i) U[k][j][i] = rcv_buf1[count++];
435 
436 /* -- restore original grid index in the y-dir -- */
437 
438  box->jb = jb0; box->je = je0;
439 
440 #endif /* PARALLEL */
441 }
int jb
Lower corner index in the x2 direction.
Definition: structs.h:349
#define BOX_LOOP(B, k, j, i)
Definition: macros.h:70
int AL_Get_cart_comm(int, MPI_Comm *)
Definition: al_sz_get.c:117
long int NX2
Number of interior zones in the X2 directions (boundaries excluded) for the local processor...
Definition: globals.h:50
#define IDIR
Definition: pluto.h:193
long int NX3_TOT
Total number of zones in the X3 direction (boundaries included) for the local processor.
Definition: globals.h:59
int j
Definition: analysis.c:2
int nghost
Number of ghost zones.
Definition: structs.h:104
int k
Definition: analysis.c:2
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
int i
Definition: analysis.c:2
int je
Upper corner index in the x2 direction.
Definition: structs.h:350
Definition: al_hidden.h:38
#define JDIR
Definition: pluto.h:194
long int JBEG
Lower grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:39
long int JEND
Upper grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:41
#define DIMENSIONS
Definition: definitions_01.h:2

Here is the call graph for this function:

Here is the caller graph for this function:

int SB_JSHIFT ( int  jc)

Make sure jc always fall between JBEG and JEND

Definition at line 638 of file sb_tools.c.

643 {
644  int jj;
645 
646  jj = jc;
647  if (jj > JEND) jj -= (int)NX2;
648  if (jj < JBEG) jj += (int)NX2;
649 
650  if (jj < JBEG || jj > JEND){
651  print (" ! j index out of range in JSHIFT %d, %d\n", jc, jj);
652  QUIT_PLUTO(1);
653  }
654 
655  return(jj);
656 }
long int NX2
Number of interior zones in the X2 directions (boundaries excluded) for the local processor...
Definition: globals.h:50
void print(const char *fmt,...)
Definition: amrPluto.cpp:497
long int JBEG
Lower grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:39
#define QUIT_PLUTO(e_code)
Definition: macros.h:125
long int JEND
Upper grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:41

Here is the call graph for this function:

Here is the caller graph for this function:

void SB_SetBoundaryVar ( double ***  U,
RBox box,
int  side,
double  t,
Grid grid 
)

Fill ghost zones using shearing-box conditions.

Parameters
[out]Upointer to a 3D array (centered or staggered)
[in]boxpointer to RBox structure defining the domain sub-portion over which shearing-box conditions have to be applied
[in]sidethe side of the X1 boundary (X1_BEG or X1_END)
[in]tthe simulation time
[in]gridpointer to an array of Grid structures
Returns
This function has no return value.

Definition at line 36 of file sb_tools.c.

50 {
51  int i, j, k, ngh_y;
52  int nghL, nghR;
53  int coords[3], dst1, dst2;
54  long int count, buf_size;
55  static double *qL, *qR;
56 
57  if (side != X1_BEG && side != X1_END){
58  print1 ("! SB_SetBoundaryVar: wrong boundary\n");
59  QUIT_PLUTO(1);
60  }
61 
62  if (qL == NULL){
63  qL = ARRAY_1D(NMAX_POINT, double);
64  qR = ARRAY_1D(NMAX_POINT, double);
65  }
66 
68 
69 /* -- get number of ghost zones to the left and to the right --*/
70 
71  nghL = JBEG - box->jb;
72  nghR = box->je - JEND;
73 
74 /* -- shift data values across parallel domains -- */
75 
76  #ifdef PARALLEL
77  if (grid[JDIR].nproc > 1) SB_ShiftBoundaryVar(U, box, side, t, grid);
78  #endif
79 
80 /* -- exchange values between processors to fill ghost zones -- */
81 
82  SB_FillBoundaryGhost(U, box, nghL, nghR, grid);
83 
84 /* ---- perform 1D interpolation in the x
85  boundary zones along the y direction ---- */
86 
87  if (side == X1_BEG){
88  for (k = box->kb; k <= box->ke; k++){
89  for (i = box->ib; i <= box->ie; i++){
90  JTOT_LOOP(j) qR[j] = U[k][j][i];
91  SB_ShearingInterp (qL, qR, t, X1_BEG, grid);
92  JDOM_LOOP(j) U[k][j][i] = qL[j];
93  }
94  }
95  }else if (side == X1_END){
96  for (k = box->kb; k <= box->ke; k++){
97  for (i = box->ib; i <= box->ie; i++){
98  JTOT_LOOP(j) qL[j] = U[k][j][i];
99  SB_ShearingInterp (qL, qR, t, X1_END, grid);
100  JDOM_LOOP(j) U[k][j][i] = qR[j];
101  }
102  }
103  }
104 
105 /* -- exchange values between processors to fill ghost zones -- */
106 
107  SB_FillBoundaryGhost (U, box, nghL, nghR, grid);
108  return;
109 }
#define X1_BEG
Boundary region at X1 beg.
Definition: pluto.h:146
int jb
Lower corner index in the x2 direction.
Definition: structs.h:349
void SB_ShearingInterp(double *qL, double *qR, double t, int side, Grid *grid)
Definition: sb_tools.c:444
void print1(const char *fmt,...)
Definition: amrPluto.cpp:511
int kb
Lower corner index in the x3 direction.
Definition: structs.h:351
#define X1_END
Boundary region at X1 end.
Definition: pluto.h:147
void SB_FillBoundaryGhost(double ***U, RBox *box, int nghL, int nghR, Grid *grid)
Definition: sb_tools.c:297
int ib
Lower corner index in the x1 direction.
Definition: structs.h:347
#define JDOM_LOOP(j)
Definition: macros.h:35
int j
Definition: analysis.c:2
if(divB==NULL)
Definition: analysis.c:10
int k
Definition: analysis.c:2
double g_domBeg[3]
Lower limits of the computational domain.
Definition: globals.h:125
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
long int NMAX_POINT
Maximum number of points among the three directions, boundaries excluded.
Definition: globals.h:62
#define JTOT_LOOP(j)
Definition: macros.h:39
int i
Definition: analysis.c:2
int je
Upper corner index in the x2 direction.
Definition: structs.h:350
double g_domEnd[3]
Upper limits of the computational domain.
Definition: globals.h:126
#define JDIR
Definition: pluto.h:194
static double sb_Ly
Definition: sb_tools.c:33
long int JBEG
Lower grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:39
#define QUIT_PLUTO(e_code)
Definition: macros.h:125
long int JEND
Upper grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:41

Here is the call graph for this function:

Here is the caller graph for this function:

void SB_ShearingInterp ( double *  qL,
double *  qR,
double  t,
int  side,
Grid grid 
)

Shift the 1D arrays qL or qR by an amount $ wt = \Delta y\Delta J + \epsilon $ (if there's only one processor in y) or just by $ \epsilon $ (otherwise) by advecting the initial profile of qR (when side == X1_BEG) or qL (when side == X1_END).

Parameters
[in,out]qL1D array containing the un-shifted values on the left boundary
[in,out]qR1D array containing the un-shifted values on the right boundary
[in]tsimulation time
[in]sideboundary side
[in]gridpointer to an array of Grid structures
Returns
This function has no return value.

Definition at line 444 of file sb_tools.c.

462 {
463  int j, Delta_j, nghost;
464  int jS, jN, jp, jm;
465  int isgn;
466  double Delta_L, Delta_y, dyfrac;
467  double scrh;
468  double *q_from, *q_to;
469  static double *dq, *dql, *flux;
470 
471  if (dq == NULL){
472  dq = ARRAY_1D(NMAX_POINT, double);
473  dql = ARRAY_1D(NMAX_POINT, double);
474  flux = ARRAY_1D(NMAX_POINT, double);
475  }
476 
477  Delta_y = grid[JDIR].dx[JBEG];
478  nghost = grid[JDIR].nghost;
479 
480  if (side == X1_BEG){
481  q_from = qR;
482  q_to = qL;
483  isgn = -1;
484  }else if (side == X1_END){
485  q_from = qL;
486  q_to = qR;
487  isgn = 1;
488  }
489 
490  Delta_L = fmod(isgn*sb_vy*t, sb_Ly);
491  scrh = Delta_L/Delta_y;
492 
493 /* ---- shift index and fractional remainder inside cell ---- */
494 
495  Delta_j = (int)scrh;
496  dyfrac = fabs(scrh) - floor(fabs(scrh));
497 
498 /* -- in parallel mode, shift has alrady been done at this point -- */
499 
500  #ifdef PARALLEL
501  if (grid[JDIR].nproc > 1) Delta_j = 0;
502  #endif
503 
504 /* -- compute limited slopes & interpolate -- */
505 
506  for (j = 1; j <= JEND + nghost; j++) {
507  dq[j] = q_from[j] - q_from[j - 1];
508  }
509 
510  #if SB_ORDER == 1 /* -- 1st order interpolation -- */
511 
512  for (j = 0; j <= JEND + nghost; j++) dql[j] = 0.0;
513 
514  if (side == X1_BEG)
515  for (j = JBEG - 1; j <= JEND; j++) flux[j] = q_from[j];
516  else if (side == X1_END)
517  for (j = JBEG - 1; j <= JEND; j++) flux[j] = q_from[j + 1];
518 
519  #elif SB_ORDER == 2 /* -------------------------------------------
520  2nd order interpolation uses the standard
521  conservative MUSCL-Hancock scheme
522  ------------------------------------------ */
523 /* vanleer_lim (dq + 1, dq, dql, JBEG - 1, JEND + 1, grid); */
524  for (j = JBEG - 1; j <= JEND + 1; j++) dql[j] = VAN_LEER(dq[j+1], dq[j]);
525 
526  if (side == X1_BEG){
527  for (j = JBEG - 1; j <= JEND; j++) {
528  flux[j] = q_from[j] + 0.5*dql[j]*(1.0 - dyfrac);
529  }
530  }else if (side == X1_END){
531  for (j = JBEG - 1; j <= JEND; j++) {
532  flux[j] = q_from[j + 1] - 0.5*dql[j + 1]*(1.0 - dyfrac);
533  }
534  }
535 
536  #elif SB_ORDER == 3 /* --------------------------------------
537  3rd order interpolation uses the
538  traditional PPM method.
539  -------------------------------------- */
540  static double *qp, *qm;
541  double ap, am, P0, P1, P2;
542 
543  if (qp == NULL){
544  qp = ARRAY_1D(NMAX_POINT, double);
545  qm = ARRAY_1D(NMAX_POINT, double);
546  if ( (JBEG - 3) < 0) {
547  printf ("! SB_ShearingInterp: the value of SB_ORDER (%d)\n",
548  SB_ORDER);
549  printf ("! is not consistent with underlying algorithm\n");
550  QUIT_PLUTO(1);
551  }
552  }
553 
554 /* mc_lim (dq + 1, dq, dql, JBEG - 2, JEND + 2, grid); */
555  for (j = JBEG - 2; j <= JEND + 2; j++) dql[j] = MC(dq[j+1], dq[j]);
556  for (j = JBEG - 1; j <= JEND + 1; j++){
557  qp[j] = 0.5*(q_from[j] + q_from[j+1]) - (dql[j+1] - dql[j])/6.0;
558  qm[j] = 0.5*(q_from[j] + q_from[j-1]) - (dql[j] - dql[j-1])/6.0;
559 
560  ap = qp[j] - q_from[j];
561  am = qm[j] - q_from[j];
562 
563  if (ap*am >= 0.0) {
564  ap = am = 0.0;
565  }else{
566  if (fabs(ap) >= 2.0*fabs(am)) ap = -2.0*am;
567  if (fabs(am) >= 2.0*fabs(ap)) am = -2.0*ap;
568  }
569  qp[j] = q_from[j] + ap;
570  qm[j] = q_from[j] + am;
571  }
572 
573  if (side == X1_BEG){
574  for (j = JBEG - 1; j <= JEND; j++){
575  P0 = 1.5*q_from[j] - 0.25*(qp[j] + qm[j]);
576  P1 = qp[j] - qm[j];
577  P2 = 3.0*(qp[j] - 2.0*q_from[j] + qm[j]);
578  flux[j] = P0 + 0.5*P1*(1.0 - dyfrac) +
579  P2*(0.25 - 0.5*dyfrac + dyfrac*dyfrac/3.0);
580  }
581  }else if (side == X1_END) {
582  for (j = JBEG - 1; j <= JEND; j++){
583  P0 = 1.5*q_from[j + 1] - 0.25*(qp[j + 1] + qm[j + 1]);
584  P1 = qp[j + 1] - qm[j + 1];
585  P2 = 3.0*(qp[j + 1] - 2.0*q_from[j + 1] + qm[j + 1]);
586  flux[j] = P0 - 0.5*P1*(1.0 - dyfrac) +
587  P2*(0.25 - 0.5*dyfrac + dyfrac*dyfrac/3.0);
588  }
589  }
590 
591  #else
592 
593  print ("! SB_ORDER should lie between 1 and 3\n");
594  QUIT_PLUTO(1);
595 
596  #endif
597 
598 /* -------------------------------------------------------------
599  Assign volumetric sliding averages.
600  The match point falls on the opposite side
601  between jS and jN = jS + 1.
602 
603  At t = 0:
604 
605  - point j on the left matches jN on the right;
606  - point j on the right matches jS on the left;
607 
608  In any case,
609 
610  (j + Delta_j) --> jN if side is X1_BEG
611  (j + Delta_j) --> jS if side is X1_BEG
612 
613  and the advection operator can be defined in terms
614  of jup = (j + Delta_j):
615 
616  q_to[j] = q_from[jup] -+ dyfrac*(flux[jup] - flux[jup-1]);
617 
618  with - (+) for left (right) if dyfrac is always positive.
619  ------------------------------------------------------------- */
620 
621  if (side == X1_END) dyfrac *= -1.0;
622 
623  if (grid[JDIR].nproc == 1){
624  for (j = JBEG; j <= JEND; j++){
625  jp = SB_JSHIFT(j + Delta_j);
626  jm = SB_JSHIFT(jp - 1);
627  q_to[j] = q_from[jp] - dyfrac*(flux[jp] - flux[jm]);
628  }
629  }else{
630  for (j = JBEG; j <= JEND; j++){
631  jp = j;
632  jm = j-1;
633  q_to[j] = q_from[jp] - dyfrac*(flux[jp] - flux[jm]);
634  }
635  }
636 }
#define X1_BEG
Boundary region at X1 beg.
Definition: pluto.h:146
tuple scrh
Definition: configure.py:200
#define SB_ORDER
Definition: shearingbox.h:29
#define VAN_LEER(a, b)
Definition: macros.h:113
#define X1_END
Boundary region at X1 end.
Definition: pluto.h:147
double * dx
Definition: structs.h:83
int SB_JSHIFT(int jc)
Definition: sb_tools.c:638
int j
Definition: analysis.c:2
int nghost
Number of ghost zones.
Definition: structs.h:104
double sb_vy
Velocity offset (>0), in SB_Boundary().
Definition: sb_boundary.c:24
void print(const char *fmt,...)
Definition: amrPluto.cpp:497
#define MC(a, b)
Definition: macros.h:114
#define ARRAY_1D(nx, type)
Definition: prototypes.h:170
long int NMAX_POINT
Maximum number of points among the three directions, boundaries excluded.
Definition: globals.h:62
#define JDIR
Definition: pluto.h:194
static double sb_Ly
Definition: sb_tools.c:33
long int JBEG
Lower grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:39
#define QUIT_PLUTO(e_code)
Definition: macros.h:125
long int JEND
Upper grid index of the computational domain in the the X2 direction for the local processor...
Definition: globals.h:41

Here is the call graph for this function:

Here is the caller graph for this function:

Variable Documentation

double sb_Ly
static

Definition at line 33 of file sb_tools.c.