/*
** The program was compiled using the zc ZPL Compiler Version 1.9.0
** Current working directory: /tmp_mnt/nfs/research/paraducks/users/sameer/rs/zpl/zpl2/home/examples
**                   command: /home/grads/sameer/z/original/src/zpl -V3 -zguard jacobi.z 
*/
#include "Profile/Profiler.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <limits.h>
#include "md_zinc.h"
#include "jacobi_reg.h"
#include "jacobi_ens.h"
#define _IRONMAN
#include "stand_inc.h"
int _allregionsflat=0;
#include "extra.h"

int numdirections=_NUM_DIRECTIONS;

typedef struct _rmsf {
  _region_pnc reg;
  _ensemble_pnc mask;
  int withflag;
} _rmsframe;

_PRIVATE _rmsframe _RMStack[_MAXRANK+1];/* this should go elsewhere */
#define _MAXENS 64

/* loop counters for mloops */
_PRIVATE int _i0, _i1, _i2, _i3, _i4, _i5;

/* loop counters for reflect mloops */
_PRIVATE int _i0d, _i0s, _i1d, _i1s, _i2d, _i2s, _i3d, _i3s, _i4d, _i4s, _i5d, _i5s;

/* communication buffer */
_PRIVATE char *_globuff;
_PRIVATE int _globuff_size = 0;

/* config var */   _PRIVATE int n;
/* config var */   _PRIVATE double delta;
/* region _AnonReg0 class=3 */
/* region R class=1 */
_PRIVATE _ens_info _E_A;
_PRIVATE _ensemble_fnc A = &(_E_A);
_PRIVATE _ens_info _E_Temp;
_PRIVATE _ensemble_fnc Temp = &(_E_Temp);
_PRIVATE double err;
/* direction #0: north rank=2 [-1 0 0 ...] */
/* direction #1: east rank=2 [0 1 0 ...] */
/* direction #2: west rank=2 [0 -1 0 ...] */
/* direction #3: south rank=2 [1 0 0 ...] */
/* region _R_north_of_R class=0 */
/* region _R_east_of_R class=0 */
/* region _R_west_of_R class=0 */
/* region _R_south_of_R class=0 */
/* region _R_IMPLICIT_A class=2 */
#include "jacobi_usr.h"
void Jacobi() {
  TAU_PROFILE("procedure Jacobi()", " ", TAU_DEFAULT);
  TAU_PROFILE_TIMER(t19, "[R]           A := 0.0;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t20, "[north of R]  A := 0.0;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t21, "[east of R]   A := 0.0;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t22, "[west of R]   A := 0.0;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t23, "[south of R]  A := 1.0;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t25, "[R]           repeat", " " , TAU_USER);
  TAU_PROFILE_TIMER(t26, "Temp := (A@north+A@east+A@west+A@south)/4.0;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t27, "err := max<< fabs(A-Temp);", " " , TAU_USER);
  TAU_PROFILE_TIMER(t28, "A := Temp;", " " , TAU_USER);
  TAU_PROFILE_TIMER(t31, "[R]           writeln(A);", " " , TAU_USER);
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = R;
    _RMStack[2].mask = NULL;

    {			/* begin MLOOP *** line 19 of jacobi.z */
      for (_i0 = _REG_MYLO(R,0); _i0 <= _REG_MYHI(R,0); _i0 += _REG_STRIDE(R,0))  {
        for (_i1 = _REG_MYLO(R,1); _i1 <= _REG_MYHI(R,1); _i1 += _REG_STRIDE(R,1))  {
	  TAU_PROFILE_START(t19);
          (*((double *)_F_ACCESS_2D(A,_i0,_i1))) = 0.0;
	  TAU_PROFILE_STOP(t19);
        }
      }
    }			/* end MLOOP */

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = _R_north_of_R;
    _RMStack[2].mask = NULL;

    {			/* begin MLOOP *** line 20 of jacobi.z */
      for (_i0 = _REG_MYLO(_R_north_of_R,0); _i0 <= _REG_MYHI(_R_north_of_R,0); _i0 += _REG_STRIDE(_R_north_of_R,0))  {
        for (_i1 = _REG_MYLO(_R_north_of_R,1); _i1 <= _REG_MYHI(_R_north_of_R,1); _i1 += _REG_STRIDE(_R_north_of_R,1))  {
	  TAU_PROFILE_START(t20);
          (*((double *)_F_ACCESS_2D(A,_i0,_i1))) = 0.0;
	  TAU_PROFILE_STOP(t20);
        }
      }
    }			/* end MLOOP */

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = _R_east_of_R;
    _RMStack[2].mask = NULL;

    {			/* begin MLOOP *** line 21 of jacobi.z */
      for (_i0 = _REG_MYLO(_R_east_of_R,0); _i0 <= _REG_MYHI(_R_east_of_R,0); _i0 += _REG_STRIDE(_R_east_of_R,0))  {
        for (_i1 = _REG_MYLO(_R_east_of_R,1); _i1 <= _REG_MYHI(_R_east_of_R,1); _i1 += _REG_STRIDE(_R_east_of_R,1))  {
	  TAU_PROFILE_START(t21);
          (*((double *)_F_ACCESS_2D(A,_i0,_i1))) = 0.0;
	  TAU_PROFILE_STOP(t21);
        }
      }
    }			/* end MLOOP */

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = _R_west_of_R;
    _RMStack[2].mask = NULL;

    {			/* begin MLOOP *** line 22 of jacobi.z */
      for (_i0 = _REG_MYLO(_R_west_of_R,0); _i0 <= _REG_MYHI(_R_west_of_R,0); _i0 += _REG_STRIDE(_R_west_of_R,0))  {
        for (_i1 = _REG_MYLO(_R_west_of_R,1); _i1 <= _REG_MYHI(_R_west_of_R,1); _i1 += _REG_STRIDE(_R_west_of_R,1))  {
	  TAU_PROFILE_START(t22);
          (*((double *)_F_ACCESS_2D(A,_i0,_i1))) = 0.0;
	  TAU_PROFILE_STOP(t22);
        }
      }
    }			/* end MLOOP */

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = _R_south_of_R;
    _RMStack[2].mask = NULL;

    {			/* begin MLOOP *** line 23 of jacobi.z */
      for (_i0 = _REG_MYLO(_R_south_of_R,0); _i0 <= _REG_MYHI(_R_south_of_R,0); _i0 += _REG_STRIDE(_R_south_of_R,0))  {
        for (_i1 = _REG_MYLO(_R_south_of_R,1); _i1 <= _REG_MYHI(_R_south_of_R,1); _i1 += _REG_STRIDE(_R_south_of_R,1))  {
	  TAU_PROFILE_START(t23);
          (*((double *)_F_ACCESS_2D(A,_i0,_i1))) = 1.0;
	  TAU_PROFILE_STOP(t23);
        }
      }
    }			/* end MLOOP */

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = R;
    _RMStack[2].mask = NULL;

   
    TAU_PROFILE_START(t25);
    do {

      /* pre-RECV (near line 26 of jacobi) */
      {
        _ensemble_pnc _ensvect[2];
        _direction _subdirvect0[] = {west,_NO_DIRECTION};
        _direction * _dirvect[2];
        unsigned int _sizevect[] = {sizeof(double)};
        _ensvect[0] = A;
        _ensvect[1] = NULL;
        _dirvect[0] = _subdirvect0;
        _dirvect[1] = NULL;
        _RHSCommI(R,_ensvect,_dirvect,_sizevect,0);
      }

      /* pre-RECV (near line 26 of jacobi) */
      {
        _ensemble_pnc _ensvect[2];
        _direction _subdirvect0[] = {south,_NO_DIRECTION};
        _direction * _dirvect[2];
        unsigned int _sizevect[] = {sizeof(double)};
        _ensvect[0] = A;
        _ensvect[1] = NULL;
        _dirvect[0] = _subdirvect0;
        _dirvect[1] = NULL;
        _RHSCommI(R,_ensvect,_dirvect,_sizevect,1);
      }

      /* pre-RECV (near line 26 of jacobi) */
      {
        _ensemble_pnc _ensvect[2];
        _direction _subdirvect0[] = {east,_NO_DIRECTION};
        _direction * _dirvect[2];
        unsigned int _sizevect[] = {sizeof(double)};
        _ensvect[0] = A;
        _ensvect[1] = NULL;
        _dirvect[0] = _subdirvect0;
        _dirvect[1] = NULL;
        _RHSCommI(R,_ensvect,_dirvect,_sizevect,2);
      }

      /* pre-RECV (near line 26 of jacobi) */
      {
        _ensemble_pnc _ensvect[2];
        _direction _subdirvect0[] = {north,_NO_DIRECTION};
        _direction * _dirvect[2];
        unsigned int _sizevect[] = {sizeof(double)};
        _ensvect[0] = A;
        _ensvect[1] = NULL;
        _dirvect[0] = _subdirvect0;
        _dirvect[1] = NULL;
        _RHSCommI(R,_ensvect,_dirvect,_sizevect,3);
      }

      /* SEND (near line 26 of jacobi) */
      _RHSCommII(0);

      /* SEND (near line 26 of jacobi) */
      _RHSCommII(1);

      /* SEND (near line 26 of jacobi) */
      _RHSCommII(2);

      /* SEND (near line 26 of jacobi) */
      _RHSCommII(3);

      /* RECV (near line 26 of jacobi) */
      _RHSCommIII(0);

      /* RECV (near line 26 of jacobi) */
      _RHSCommIII(1);

      /* RECV (near line 26 of jacobi) */
      _RHSCommIII(2);

      /* RECV (near line 26 of jacobi) */
      _RHSCommIII(3);
      {			/* begin MLOOP *** line 26 of jacobi.z */
        for (_i0 = _REG_MYLO(R,0); _i0 <= _REG_MYHI(R,0); _i0 += _REG_STRIDE(R,0))  {
          for (_i1 = _REG_MYLO(R,1); _i1 <= _REG_MYHI(R,1); _i1 += _REG_STRIDE(R,1))  {
	    TAU_PROFILE_START(t26);
            (*((double *)_F_ACCESS_2D(Temp,_i0,_i1))) = ((*((double *)_F_ACCESS_2D(A,_i0-1,_i1))) + (*((double *)_F_ACCESS_2D(A,_i0,_i1+1))) + (*((double *)_F_ACCESS_2D(A,_i0,_i1-1))) + (*((double *)_F_ACCESS_2D(A,_i0+1,_i1)))) / 4.0;
	    TAU_PROFILE_STOP(t26);
          }
        }
      }			/* end MLOOP */
      { /* begin Reduce (line 27) */
        double _red_in;
        double _red_out;

        _red_in=_MAX_double_IDENTITY;
        for (_i0=_REG_MYLO(R,0);_i0<=_REG_MYHI(R,0);_i0++) {
          for (_i1=_REG_MYLO(R,1);_i1<=_REG_MYHI(R,1);_i1++) {
	    TAU_PROFILE_START(t27);
            _MAX_STMT(_red_in,fabs((*((double *)_F_ACCESS_2D(A,_i0,_i1))) - (*((double *)_F_ACCESS_2D(Temp,_i0,_i1)))));
	    TAU_PROFILE_STOP(t27);
          }
        }
        _globalReduceRoutinedouble(&_red_in,&_red_out,NULL,R,3,1,_OP_MAX);
        _RedBcastSimple(&_red_out,sizeof(double),0,5);
        err = _red_out;
      } /* end Reduce (line 27) */

      /* post-SEND (near line 28 of jacobi) */
      _RHSCommIV(0);

      /* post-SEND (near line 28 of jacobi) */
      _RHSCommIV(1);

      /* post-SEND (near line 28 of jacobi) */
      _RHSCommIV(2);

      /* post-SEND (near line 28 of jacobi) */
      _RHSCommIV(3);
      {			/* begin MLOOP *** line 28 of jacobi.z */
        for (_i0 = _REG_MYLO(R,0); _i0 <= _REG_MYHI(R,0); _i0 += _REG_STRIDE(R,0))  {
          for (_i1 = _REG_MYLO(R,1); _i1 <= _REG_MYHI(R,1); _i1 += _REG_STRIDE(R,1))  {
	    TAU_PROFILE_START(t28);
            (*((double *)_F_ACCESS_2D(A,_i0,_i1))) = (*((double *)_F_ACCESS_2D(Temp,_i0,_i1)));
	    TAU_PROFILE_STOP(t28);
          }
        }
      }			/* end MLOOP */
    } while (!(err < delta));
    TAU_PROFILE_STOP(t25);

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  {  /* Push region scope */
    _region _Tempreg2 = _RMStack[2].reg;
    _ensemble _TempMask2 = _RMStack[2].mask;

    _RMStack[2].reg = R;
    _RMStack[2].mask = NULL;

    TAU_PROFILE_START(t31);
    _StreamEnsembleTxt(zout,R,A,_ZIO_W,_StreamOut_double,_Z_W_double);
    TAU_PROFILE_STOP(t31);
    _SCALAR_LINEFEED(zout);

    /* Pop region scope */ 
    _RMStack[2].reg = _Tempreg2;
    _RMStack[2].mask = _TempMask2;
  }  /* End region scope node */
  _retpt:;
}

_PRIVATE int _cfginit[2] = { 0, 0};
const int _max_ens_comm=1;

void _ZPL_main(int argc, char *argv[]) {
  TAU_PROFILE("_ZPL_main()", "void (int, char **)", TAU_DEFAULT);
  TAU_PROFILE_INIT(argc, argv);
  TAU_PROFILE_SET_NODE(0);
  extern int zcmapsize;
  extern int zcmap[];

  /* These lines, though useless, are required by ZGuard */
  zcmapsize=zcmapsize;
  zcmap[0]=zcmap[0];

  _InitIronman(5);
  Jacobi();
}


int zcmapsize = 31;
int zcmap[31] = {
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	-1,
	66,
	85,
	104,
	123,
	142,
	-1,
	161,
	238,
	245,
	271,
	-1,
	-1,
	291 };


void _AssignToConfig(char * name,char * val) {
  if (!strcmp(name,"n")) {
    n=atoi(val);
    _cfginit[0]=1;
  } else if (!strcmp(name,"delta")) {
    delta=atof(val);
    _cfginit[1]=1;
  } else {
    if (_INDEX == 0) {
      printf("There is no assignable config var named \"%s\"\n",name);
    }
    exit(222);
  }
}




void _InitExprConfigs() {
  if (_cfginit[0]==0) {
    n = 8;
  }
  if (_cfginit[1]==0) {
    delta = 0.00001;
  }
}


int _firstdir[_MAXRANK+1] = {north,north,_NUM_DIRECTIONS,_NUM_DIRECTIONS,_NUM_DIRECTIONS,_NUM_DIRECTIONS,_NUM_DIRECTIONS};

void _SetupRegionForDirectionComm(_region_fnc R,_direction dir) {
  int proc[2];
  int lo;
  int hi;

  switch (dir) {
  case north:
    _InitRecvNegComp(R,north,0,&(proc[0]),-1);
    _InitCommZeroComp(R,north,1,_RECV,&(proc[1]));
    _SetProc(R,north,proc,_RECV);
    _InitSendNegComp(R,north,0,&(proc[0]),-1);
    _InitCommZeroComp(R,north,1,_SEND,&(proc[1]));
    _SetProc(R,north,proc,_SEND);
    break;
  case south:
    _InitRecvPosComp(R,south,0,&(proc[0]),1);
    _InitCommZeroComp(R,south,1,_RECV,&(proc[1]));
    _SetProc(R,south,proc,_RECV);
    _InitSendPosComp(R,south,0,&(proc[0]),1);
    _InitCommZeroComp(R,south,1,_SEND,&(proc[1]));
    _SetProc(R,south,proc,_SEND);
    break;
  case east:
    _InitCommZeroComp(R,east,0,_RECV,&(proc[0]));
    _InitRecvPosComp(R,east,1,&(proc[1]),1);
    _SetProc(R,east,proc,_RECV);
    _InitCommZeroComp(R,east,0,_SEND,&(proc[0]));
    _InitSendPosComp(R,east,1,&(proc[1]),1);
    _SetProc(R,east,proc,_SEND);
    break;
  case west:
    _InitCommZeroComp(R,west,0,_RECV,&(proc[0]));
    _InitRecvNegComp(R,west,1,&(proc[1]),-1);
    _SetProc(R,west,proc,_RECV);
    _InitCommZeroComp(R,west,0,_SEND,&(proc[0]));
    _InitSendNegComp(R,west,1,&(proc[1]),-1);
    _SetProc(R,west,proc,_SEND);
    break;
  default:
    fprintf(stderr,"ERROR: Trying to use illegal direction: %d\n",dir);
    break;
  }
  if (_I_SEND_RHS(R,dir) == _INDEX) {
    _I_SEND_RHS(R,dir) = -1;
  }
  if (_I_RECV_RHS(R,dir) == _INDEX) {
    _I_RECV_RHS(R,dir) = -1;
  }
}

void _SetupRegionWithDirections(_region_fnc R,int rank) {
  _direction dir;

  for (dir=(_direction)_firstdir[rank-1];dir<(_direction)_firstdir[rank];
	dir=(_direction) (dir+1)) {
    _SetupRegionForDirectionComm(R,dir);
  }
}

void _MarkCommUninitialized(_region_fnc R,int rank) {
  _direction dir;

  for (dir=(_direction)_firstdir[rank-1];dir<(_direction)_firstdir[rank];
        dir=(_direction) (dir+1)) {
    _I_SEND_RHS(R,dir) = -2;
  }
}

_PRIVATE static _reg_info _R;
_PRIVATE _region_fnc R=(&_R);

void _SetupRegionR(int *lo,int *hi,int *ilo,int *ihi) {
  int i;

  _NUMDIMS(R) = 2;
  _REG_GLOB_LO(R,0)=1;
  _REG_GLOB_HI(R,0)=n;
  _REG_STRIDE(R,0) = 1;
  _REG_GLOB_LO(R,1)=1;
  _REG_GLOB_HI(R,1)=n;
  _REG_STRIDE(R,1) = 1;
  for (i=0;i<2;i++) {
    if (_REG_GLOB_LO(R,i)<lo[i]) {
      lo[i] = _REG_GLOB_LO(R,i);
    }
    if (_REG_GLOB_HI(R,i)>hi[i]) {
      hi[i]=_REG_GLOB_HI(R,i);
    }
  }

  _InitRegionModule(lo,hi);

  if (_T_BEGOFCOL && ilo[0] < _MY_LO_BOUND(0)) {
    _MY_LO_BOUND(0) = ilo[0];
  }

  if (_T_BEGOFROW && ilo[1] < _MY_LO_BOUND(1)) {
    _MY_LO_BOUND(1) = ilo[1];
  }

  if (_T_ENDOFCOL && ihi[0] > _MY_HI_BOUND(0)) {
    _MY_HI_BOUND(0) = ihi[0];
  }

  if (_T_ENDOFROW && ihi[1] > _MY_HI_BOUND(1)) {
    _MY_HI_BOUND(1) = ihi[1];
  }

  _SetupRegion(R);
  _SetupRegionWithDirections(R,2);
}

_PRIVATE static _reg_info __R_north_of_R;
_PRIVATE _region_fnc _R_north_of_R=(&__R_north_of_R);

void _SetupRegion_R_north_of_R(int *lo,int *hi,int *ilo,int *ihi) {
  int i;

  _NUMDIMS(_R_north_of_R) = 2;
  _REG_GLOB_LO(_R_north_of_R,0)=1 + -1;
  _REG_GLOB_HI(_R_north_of_R,0)=1 - 1;
  _REG_STRIDE(_R_north_of_R,0) = 1;
  _REG_GLOB_LO(_R_north_of_R,1)=1;
  _REG_GLOB_HI(_R_north_of_R,1)=n;
  _REG_STRIDE(_R_north_of_R,1) = 1;

  _SetupRegionR(lo,hi,ilo,ihi);

  _SetupRegion(_R_north_of_R);
  _SetupRegionWithDirections(_R_north_of_R,2);
  _I_SEND_WRAP(_R_north_of_R) = (_OWN_REG(R) && (_T_ATBOT(R)) ? (_ROW_COL_TO_PROC(_TOP_ROW(_R_north_of_R),_MYCOL)) : (_NO_PROCESSOR));
  _I_RECV_WRAP(_R_north_of_R) = (_OWN_REG(_R_north_of_R) && (_T_ATTOP(_R_north_of_R)) ? (_ROW_COL_TO_PROC(_BOT_ROW(R),_MYCOL)) : (_NO_PROCESSOR));
  _WRAP_SEND_LO(_R_north_of_R,0) = _REG_MYHI(R,0);
  _WRAP_SEND_HI(_R_north_of_R,0) = _REG_MYHI(R,0);
  _WRAP_SEND_LO(_R_north_of_R,1) = _REG_MYLO(R,1);
  _WRAP_SEND_HI(_R_north_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_LO(_R_north_of_R,0) = _REG_MYLO(R,0);
  _REFLECT_SRC_HI(_R_north_of_R,0) = _REG_MYLO(R,0);
  _REFLECT_SRC_LO(_R_north_of_R,1) = _REG_MYLO(R,1);
  _REFLECT_SRC_HI(_R_north_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_STEP(_R_north_of_R,0) = -1;
  _REFLECT_SRC_STEP(_R_north_of_R,1) = 1;
}

_PRIVATE static _reg_info __R_east_of_R;
_PRIVATE _region_fnc _R_east_of_R=(&__R_east_of_R);

void _SetupRegion_R_east_of_R(int *lo,int *hi,int *ilo,int *ihi) {
  int i;

  _NUMDIMS(_R_east_of_R) = 2;
  _REG_GLOB_LO(_R_east_of_R,0)=1;
  _REG_GLOB_HI(_R_east_of_R,0)=n;
  _REG_STRIDE(_R_east_of_R,0) = 1;
  _REG_GLOB_LO(_R_east_of_R,1)=n + 1;
  _REG_GLOB_HI(_R_east_of_R,1)=n + 1;
  _REG_STRIDE(_R_east_of_R,1) = 1;

  _SetupRegion_R_north_of_R(lo,hi,ilo,ihi);

  _SetupRegion(_R_east_of_R);
  _SetupRegionWithDirections(_R_east_of_R,2);
  _I_SEND_WRAP(_R_east_of_R) = (_OWN_REG(R) && (_T_ATLFT(R)) ? (_ROW_COL_TO_PROC(_MYROW,_RGT_COL(_R_east_of_R))) : (_NO_PROCESSOR));
  _I_RECV_WRAP(_R_east_of_R) = (_OWN_REG(_R_east_of_R) && (_T_ATRGT(_R_east_of_R)) ? (_ROW_COL_TO_PROC(_MYROW,_LFT_COL(R))) : (_NO_PROCESSOR));
  _WRAP_SEND_LO(_R_east_of_R,0) = _REG_MYLO(R,0);
  _WRAP_SEND_HI(_R_east_of_R,0) = _REG_MYHI(R,0);
  _WRAP_SEND_LO(_R_east_of_R,1) = _REG_MYLO(R,1);
  _WRAP_SEND_HI(_R_east_of_R,1) = _REG_MYLO(R,1);
  _REFLECT_SRC_LO(_R_east_of_R,0) = _REG_MYLO(R,0);
  _REFLECT_SRC_HI(_R_east_of_R,0) = _REG_MYHI(R,0);
  _REFLECT_SRC_LO(_R_east_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_HI(_R_east_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_STEP(_R_east_of_R,0) = 1;
  _REFLECT_SRC_STEP(_R_east_of_R,1) = -1;
}

_PRIVATE static _reg_info __R_west_of_R;
_PRIVATE _region_fnc _R_west_of_R=(&__R_west_of_R);

void _SetupRegion_R_west_of_R(int *lo,int *hi,int *ilo,int *ihi) {
  int i;

  _NUMDIMS(_R_west_of_R) = 2;
  _REG_GLOB_LO(_R_west_of_R,0)=1;
  _REG_GLOB_HI(_R_west_of_R,0)=n;
  _REG_STRIDE(_R_west_of_R,0) = 1;
  _REG_GLOB_LO(_R_west_of_R,1)=1 + -1;
  _REG_GLOB_HI(_R_west_of_R,1)=1 - 1;
  _REG_STRIDE(_R_west_of_R,1) = 1;

  _SetupRegion_R_east_of_R(lo,hi,ilo,ihi);

  _SetupRegion(_R_west_of_R);
  _SetupRegionWithDirections(_R_west_of_R,2);
  _I_SEND_WRAP(_R_west_of_R) = (_OWN_REG(R) && (_T_ATRGT(R)) ? (_ROW_COL_TO_PROC(_MYROW,_LFT_COL(_R_west_of_R))) : (_NO_PROCESSOR));
  _I_RECV_WRAP(_R_west_of_R) = (_OWN_REG(_R_west_of_R) && (_T_ATLFT(_R_west_of_R)) ? (_ROW_COL_TO_PROC(_MYROW,_RGT_COL(R))) : (_NO_PROCESSOR));
  _WRAP_SEND_LO(_R_west_of_R,0) = _REG_MYLO(R,0);
  _WRAP_SEND_HI(_R_west_of_R,0) = _REG_MYHI(R,0);
  _WRAP_SEND_LO(_R_west_of_R,1) = _REG_MYHI(R,1);
  _WRAP_SEND_HI(_R_west_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_LO(_R_west_of_R,0) = _REG_MYLO(R,0);
  _REFLECT_SRC_HI(_R_west_of_R,0) = _REG_MYHI(R,0);
  _REFLECT_SRC_LO(_R_west_of_R,1) = _REG_MYLO(R,1);
  _REFLECT_SRC_HI(_R_west_of_R,1) = _REG_MYLO(R,1);
  _REFLECT_SRC_STEP(_R_west_of_R,0) = 1;
  _REFLECT_SRC_STEP(_R_west_of_R,1) = -1;
}

_PRIVATE static _reg_info __R_south_of_R;
_PRIVATE _region_fnc _R_south_of_R=(&__R_south_of_R);

void _SetupRegion_R_south_of_R(int *lo,int *hi,int *ilo,int *ihi) {
  int i;

  _NUMDIMS(_R_south_of_R) = 2;
  _REG_GLOB_LO(_R_south_of_R,0)=n + 1;
  _REG_GLOB_HI(_R_south_of_R,0)=n + 1;
  _REG_STRIDE(_R_south_of_R,0) = 1;
  _REG_GLOB_LO(_R_south_of_R,1)=1;
  _REG_GLOB_HI(_R_south_of_R,1)=n;
  _REG_STRIDE(_R_south_of_R,1) = 1;

  _SetupRegion_R_west_of_R(lo,hi,ilo,ihi);

  _SetupRegion(_R_south_of_R);
  _SetupRegionWithDirections(_R_south_of_R,2);
  _I_SEND_WRAP(_R_south_of_R) = (_OWN_REG(R) && (_T_ATTOP(R)) ? (_ROW_COL_TO_PROC(_BOT_ROW(_R_south_of_R),_MYCOL)) : (_NO_PROCESSOR));
  _I_RECV_WRAP(_R_south_of_R) = (_OWN_REG(_R_south_of_R) && (_T_ATBOT(_R_south_of_R)) ? (_ROW_COL_TO_PROC(_TOP_ROW(R),_MYCOL)) : (_NO_PROCESSOR));
  _WRAP_SEND_LO(_R_south_of_R,0) = _REG_MYLO(R,0);
  _WRAP_SEND_HI(_R_south_of_R,0) = _REG_MYLO(R,0);
  _WRAP_SEND_LO(_R_south_of_R,1) = _REG_MYLO(R,1);
  _WRAP_SEND_HI(_R_south_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_LO(_R_south_of_R,0) = _REG_MYHI(R,0);
  _REFLECT_SRC_HI(_R_south_of_R,0) = _REG_MYHI(R,0);
  _REFLECT_SRC_LO(_R_south_of_R,1) = _REG_MYLO(R,1);
  _REFLECT_SRC_HI(_R_south_of_R,1) = _REG_MYHI(R,1);
  _REFLECT_SRC_STEP(_R_south_of_R,0) = -1;
  _REFLECT_SRC_STEP(_R_south_of_R,1) = 1;
}

_PRIVATE static _reg_info __R_IMPLICIT_A;
_PRIVATE _region_fnc _R_IMPLICIT_A=(&__R_IMPLICIT_A);

void _SetupRegion_R_IMPLICIT_A(int *lo,int *hi,int *ilo,int *ihi) {
  int i;

  _NUMDIMS(_R_IMPLICIT_A) = 2;
  _REG_GLOB_LO(_R_IMPLICIT_A,0)=1 - 1;
  _REG_GLOB_HI(_R_IMPLICIT_A,0)=n + 1;
  _REG_STRIDE(_R_IMPLICIT_A,0) = 1;
  _REG_GLOB_LO(_R_IMPLICIT_A,1)=1 - 1;
  _REG_GLOB_HI(_R_IMPLICIT_A,1)=n + 1;
  _REG_STRIDE(_R_IMPLICIT_A,1) = 1;
  for (i=0;i<2;i++) {
    if (_REG_GLOB_LO(_R_IMPLICIT_A,i)<ilo[i]) {
      ilo[i] = _REG_GLOB_LO(_R_IMPLICIT_A,i);
    }
    if (_REG_GLOB_HI(_R_IMPLICIT_A,i)>ihi[i]) {
      ihi[i]=_REG_GLOB_HI(_R_IMPLICIT_A,i);
    }
  }

  _SetupRegion_R_south_of_R(lo,hi,ilo,ihi);

  _SetupRegion(_R_IMPLICIT_A);
  _SetupRegionWithDirections(_R_IMPLICIT_A,2);
}

void _InitAllRegions() {
  int lo[_MAXRANK] = {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX};
  int hi[_MAXRANK] = {INT_MIN,INT_MIN,INT_MIN,INT_MIN,INT_MIN,INT_MIN};
  int ilo[_MAXRANK] = {INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX,INT_MAX};
  int ihi[_MAXRANK] = {INT_MIN,INT_MIN,INT_MIN,INT_MIN,INT_MIN,INT_MIN};
  _SetupRegion_R_IMPLICIT_A(lo,hi,ilo,ihi);
}
void _SetupEnsemble_A() {
  {
    int lofluff0=0;
    int hifluff0=0;
    int lofluff1=0;
    int hifluff1=0;
    if (!_T_BEG_OF_MESH(0)) {
      lofluff0=1;
    }
    if (!_T_END_OF_MESH(0)) {
      hifluff0=1;
    }
    if (!_T_BEG_OF_MESH(1)) {
      lofluff1=1;
    }
    if (!_T_END_OF_MESH(1)) {
      hifluff1=1;
    }
    _ENS_STR(A,0)=1;
    _ENS_OFF(A,0)=_REG_MYLO(_R_IMPLICIT_A,0)-(lofluff0*_ENS_STR(A,0));
    _ENS_STR(A,1)=1;
    _ENS_OFF(A,1)=_REG_MYLO(_R_IMPLICIT_A,1)-(lofluff1*_ENS_STR(A,1));
    A->blocksize[1]=sizeof(double);
    A->blocksize[0]=A->blocksize[1]*((_REG_MYHI(_R_IMPLICIT_A,1)-_REG_MYLO(_R_IMPLICIT_A,1)+1)+lofluff1+hifluff1);
    A->impl_regptr=_R_IMPLICIT_A;
    A->size=A->blocksize[0]*((_REG_MYHI(_R_IMPLICIT_A,0)-_REG_MYLO(_R_IMPLICIT_A,0)+1)+lofluff0+hifluff0);
    A->data=(void *)_ZPL_ALLOC(A->size);
    A->origin=(((char *)(A->data))-(
              _ENS_OFF(A,0)* A->blocksize[0]
              +_ENS_OFF(A,1)* A->blocksize[1]
              ));
    A->basetype=_TYPE_DOUBLE;
    A->Writefn=NULL;
    A->Readfn=NULL;
  }
}


void _DestroyEnsemble_A() {
  _ZPL_FREE(A->data);
}


void _SetupEnsemble_Temp() {
  _SetupEnsemble_A();

  {
    int lofluff0=0;
    int hifluff0=0;
    int lofluff1=0;
    int hifluff1=0;
    _ENS_STR(Temp,0)=1;
    _ENS_OFF(Temp,0)=_REG_MYLO(R,0)-(lofluff0*_ENS_STR(Temp,0));
    _ENS_STR(Temp,1)=1;
    _ENS_OFF(Temp,1)=_REG_MYLO(R,1)-(lofluff1*_ENS_STR(Temp,1));
    Temp->blocksize[1]=sizeof(double);
    Temp->blocksize[0]=Temp->blocksize[1]*((_REG_MYHI(R,1)-_REG_MYLO(R,1)+1)+lofluff1+hifluff1);
    Temp->impl_regptr=R;
    Temp->size=Temp->blocksize[0]*((_REG_MYHI(R,0)-_REG_MYLO(R,0)+1)+lofluff0+hifluff0);
    Temp->data=(void *)_ZPL_ALLOC(Temp->size);
    Temp->origin=(((char *)(Temp->data))-(
              _ENS_OFF(Temp,0)* Temp->blocksize[0]
              +_ENS_OFF(Temp,1)* Temp->blocksize[1]
              ));
    Temp->basetype=_TYPE_DOUBLE;
    Temp->Writefn=NULL;
    Temp->Readfn=NULL;
  }
}


void _DestroyEnsemble_Temp() {
  _DestroyEnsemble_A();

  _ZPL_FREE(Temp->data);
}


void _InitGlobalEnsembles() {
  _SetupEnsemble_Temp();
}


void _DestroyGlobalEnsembles() {
  _DestroyEnsemble_Temp();
}


