void write_grid_file(void) {
/*    The following subroutine saves the depth, reduced gravity of    */
/*  each interface, the potential density of each layer, and the      */
/*  Coriolis parameter.  A variety of metric terms are written to a   */
/*  separate file.                                                    */
  char filename[40];           /* The file name of the save file.     */
  char filepath[120];          /* The path (dir/file) to the file.    */
  int i, j, cdfid, timeid;
  size_t err = 1;

  struct varcdfinfo varinfo[10];
/*   vardesc is a structure defined in HIM_io.h.   The elements of    */
/* this structure, in order, are: (1) the variable name for the NetCDF*/
/* file; (2) the variable's long name; (3) a character indicating the */
/* horizontal grid, which may be '1' (column), 'h', 'q', 'u', or 'v', */
/* for the corresponding C-grid variable; (4) a character indicating  */
/* the vertical grid, which may be 'L' (layer), 'i' (interface),      */
/* '2' (mixed-layers), or '1' (no vertical location); (5) a character */
/* indicating the time levels of the field, which may be 's' (snap-   */
/* shot), 'a' (average between snapshots), 'm' (monthly average), or  */
/* '1' (no time variation); (6) the variable's units; and (7) a       */
/* character indicating the size in memory to write, which may be     */
/* 'd' (8-byte) or 'f' (4-byte).                                      */
  vardesc vars[4] = {
    {"D","Basin Depth",'h','1','1',"meter", 'd'},
    {"g","Reduced gravity",'1','L','1',"meter second-2", 'd'},
    {"R","Target Potential Density",'1','L','1',"kilogram meter-3", 'd'},
    {"f","Coriolis Parameter",'q','1','1',"second-1", 'd'}
  };

  sprintf(filename,"D.%d.%d.%d",NXTOT,NYTOT,NZ);
  strcpy(filepath, directory);
  strcat(filepath, filename);

  create_file(filepath, vars, 4, &cdfid, &timeid, varinfo);
  err *= write_field(cdfid, vars[0], varinfo[0], 0, D[0]);
  err *= write_field(cdfid, vars[1], varinfo[1], 0, g);
  err *= write_field(cdfid, vars[2], varinfo[2], 0, Rlay);
  err *= write_field(cdfid, vars[3], varinfo[3], 0, f[0]);

  close_file(&cdfid);
  if (err == 0)
    printf("Problems saving general parameters.\n");

  {
/* ### REVISIT THIS PART OF THE ROUTINE AFTER METRICS... ### */
    double out[NYMEM][NXMEM];     /* An array for output.  */
    extern double hmask[NYMEM][NXMEM];

    vardesc vars2[10]={
      {"geolatb","latitude at q points",'q','1','1',"degree",'d'},
      {"geolonb","longitude at q points",'q','1','1',"degree",'d'},
      {"wet", "land or ocean?", 'h','1','1',"none",'d'},
      {"geolat", "latitude at h points", 'h','1','1',"degree",'d'},
      {"geolon","longitude at h points",'h','1','1',"degree",'d'},
      {"dxh","Zonal grid spacing at h points",'h','1','1',"m",'d'},
      {"dxq","Zonal grid spacing at q points",'q','1','1',"m",'d'},
      {"dyh","Meridional grid spacing at h points",'h','1','1',"m",'d'},
      {"dyq","Meridional grid spacing at q points",'q','1','1',"m",'d'},
      {"Ah","Area of h cells",'h','1','1',"m2",'d'},
    };

    sprintf(filename,"grid.%d.%d",NXTOT,NYTOT);
    strcpy(filepath, directory);
    strcat(filepath, filename);

    create_file(filepath, vars2, 10, &cdfid, &timeid, varinfo);
    err *= write_field(cdfid, vars2[0], varinfo[0], 0, geolatq[0]);
    err *= write_field(cdfid, vars2[1], varinfo[1], 0, geolonq[0]);
    err *= write_field(cdfid, vars2[2], varinfo[2], 0, hmask[0]);
    err *= write_field(cdfid, vars2[3], varinfo[3], 0, geolath[0]);
    err *= write_field(cdfid, vars2[4], varinfo[4], 0, geolonh[0]);

    for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DXh(j,i);
    err *= write_field(cdfid, vars2[5], varinfo[5], 0, out[0]);
    for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DXq(j,i);
    err *= write_field(cdfid, vars2[6], varinfo[6], 0, out[0]);
    for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DYh(j,i);
    err *= write_field(cdfid, vars2[7], varinfo[7], 0, out[0]);
    for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DYq(j,i);
    err *= write_field(cdfid, vars2[8], varinfo[8], 0, out[0]);
    for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DXDYh(j,i);
    err *= write_field(cdfid, vars2[9], varinfo[9], 0, out[0]);

    close_file(&cdfid);

    if (err == 0)
      printf("Problems saving latitude and longitude and wet.\n");
  }
}
Exemple #2
0
void set_metrics(void)
{
  int i,j;
  extern double areagr[NXMEM][NYMEM];
  double Iareagr[NXMEM][NYMEM];

/*    Calculate the values of the metric terms that might be used     */
/*  and save them in arrays.                                          */

#ifdef CARTESIAN
/*   On a cartesian grid, the various DX... and DY... macros all      */
/* point to the same scalars.                                         */
  i = 0; j = 0;
  DXh(i,j) = RE * LENLON * M_PI / (180.0 * NXTOT);
  DYh(i,j) = RE * LENLAT * M_PI / (180.0 * NYTOT);
  IDXh(i,j) = 1.0 / DXh(i,j);
  IDYh(i,j) = 1.0 / DYh(i,j);
  DXDYh(i,j) = DXh(i,j) * DYh(i,j);
  IDXDYh(i,j) = IDXh(i,j) * IDYh(i,j);
  for (j=Y0-1;j<=ny+2;j++)
    latq[j] = LOWLAT + LENLAT*(double)(j-Y0+Y0abs)/(double)NYTOT;
  for (j=Y0;j<=ny;j++)
    lath[j] = LOWLAT + LENLAT*((double)(j-Y0+Y0abs)-0.5)/(double)NYTOT;
  for (i=X0-1;i<=nx+2;i++)
    lonq[i] = WESTLON + LENLON*(double)(i-X0+X0abs)/(double)NXTOT;
  for (i=X0;i<=nx;i++)
    lonh[i] = WESTLON + LENLON*((double)(i-X0+X0abs)-0.5)/(double)NXTOT;
# if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT)
  for (j=Y0;j<=NYTOT+Y0;j++)
    latq_tot[j] = LOWLAT + LENLAT*(double)(j-Y0)/(double)NYTOT;
  for (j=Y0;j<=NYTOT+Y0;j++)
    lath_tot[j] = LOWLAT + LENLAT*((double)(j-Y0)-0.5)/(double)NYTOT;
# endif
# if defined(PARALLEL_X) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT)
  for (i=X0;i<=NXTOT+X0;i++)
    lonq_tot[i] = WESTLON + LENLON*(double)(i-X0)/(double)NXTOT;
  for (i=X0;i<=NXTOT+X0;i++)
    lonh_tot[i] = WESTLON + LENLON*((double)(i-X0)-0.5)/(double)NXTOT;
# endif
#else

/*   All of the metric terms should be defined over the domain from   */
/* X0-1 to nx+2.  Outside of the physical domain, both the metrics    */
/* and their inverses may be set to zero.                             */
/*   Any points that are outside of the computational domain should   */
/* have their values set to zero _BEFORE_ setting the other metric    */
/* terms, because these macros may or may not expand to 2-dimensional */
/* arrays.                                                            */

/*  The metric terms within the computational domain are set here.    */

# ifdef ISOTROPIC

  {
    double C0, I_C0, yq, yh, jd;
    double fnRef, yRef; /* fnRef is the value of the integral of      */
                        /* 1/(dx*cos(lat)) from the equator to a      */
                        /* reference latitude, while yRef is the      */
                        /* j-index of that reference latitude.        */
    int itt1, itt2;

    C0 = M_PI*((double) LENLON / (double) (180*NXTOT)); I_C0 = 1.0 / C0;

/*    With an isotropic grid, the north-south extent of the domain,   */
/*  the east-west extent, and the number of grid points in each       */
/*  direction are _not_ independent.  Here the north-south extent     */
/*  will be determined to fit the east-west extent and the number of  */
/*  grid points.  The grid is perfectly isotropic.                    */
#  ifdef NORTHREFERENCE
/*  The following 2 lines fixes the refererence latitude at the       */
/*  northern edge of the domain, LOWLAT+LENLAT at j=NYTOT+Y0.         */
    yRef = Y0abs - Y0 - NYTOT;
    fnRef = I_C0 * INTSECY(((LOWLAT+LENLAT)*M_PI/180.0));
#  else
/*  The following line sets the refererence latitude LOWLAT at j=Y0.  */
    yRef = Y0abs - Y0;   fnRef = I_C0 * INTSECY((LOWLAT*M_PI/180.0));
#  endif

/*  Everything else should pretty much work.                          */
    yq = LOWLAT*M_PI/180.0;
/* If the model is in parallel in the Y-direction, do the same set of */
/* calculations which would occur on a single processor.              */
    for (j=Y0-1-Y0abs;j<Y0-1;j++) {
      jd = fnRef + (double) (j + yRef) - 0.5;
      yh = find_root(jd,yq,&itt1);

      jd = fnRef + (double) (j + yRef);
      yq = find_root(jd,yh,&itt2);
#  if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT)
      latq_tot[j+Y0abs] = yq*180.0/M_PI;
      lath_tot[j+Y0abs] = yh*180.0/M_PI;
#  endif
    }
    
    for (j=Y0-1;j<=ny+2;j++) {
      jd = fnRef + (double) (j + yRef) - 0.5;
      yh = find_root(jd,yq,&itt1);

      jd = fnRef + (double) (j + yRef);
      yq = find_root(jd,yh,&itt2);

      latq[j] = yq*180.0/M_PI;
      lath[j] = yh*180.0/M_PI;
#  if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT)
      latq_tot[j+Y0abs] = yq*180.0/M_PI;
      lath_tot[j+Y0abs] = yh*180.0/M_PI;
#  endif

      for (i=X0-1;i<=nx+2;i++) {
        DXq(i,j) = cos(yq) * (RE * C0);
        DYq(i,j) = DXq(i,j);

        DXv(i,j) = DXq(i,j);
        DYv(i,j) = DYq(i,j);

        DXh(i,j) = cos(yh) * (RE * C0);
        DYh(i,j) = DXh(i,j);

        DXu(i,j) = DXh(i,j);
        DYu(i,j) = DYh(i,j);
      }
    }
#  if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT)
    for (j=ny+3;j<=NYTOT+Y0-Y0abs;j++) {
      jd = fnRef + (double) (j + yRef) - 0.5;
      yh = find_root(jd,yq,&itt1);

      jd = fnRef + (double) (j + yRef);
      yq = find_root(jd,yh,&itt2);
      latq_tot[j+Y0abs] = yq*180.0/M_PI;
      lath_tot[j+Y0abs] = yh*180.0/M_PI;
    }
#  endif
  }
  for (i=X0-1;i<=nx+2;i++)
    lonq[i] = WESTLON + LENLON*(double)(i-X0+X0abs)/(double)NXTOT;
  for (i=X0;i<=nx;i++)
    lonh[i] = WESTLON + LENLON*((double)(i-X0+X0abs)-0.5)/(double)NXTOT;
#  if defined(PARALLEL_X) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT)
  for (i=X0;i<=NXTOT+X0;i++)
    lonq_tot[i] = WESTLON + LENLON*(double)(i-X0)/(double)NXTOT;
  for (i=X0;i<=NXTOT+X0;i++)
    lonh_tot[i] = WESTLON + LENLON*((double)(i-X0)-0.5)/(double)NXTOT;
#  endif

# else         /*  ISOTROPIC  */

/* This code implements latitude/longitude coordinates on a sphere.   */

//BX-a
//    for (j=0;j<=NYTOT-1;j++) {
//HF    for (j=Y0-1;j<=ny+2;j++) {
   for (j=2;j<NYTOT+2;j++) {
	latq[j] = qlat[j];
	lath[j] = hlat[j];
    }
//BX-e
/* HF  for (i=0;i<=NXTOT-1;i++) {
    for (j=0;j<=NYTOT-1;j++) {
        DXq(i+2,j+2) = dxq[j][i];
	DYq(i+2,j+2) = dyq[j][i];
	DXv(i+2,j+2) = dxv[j][i];
	DYv(i+2,j+2) = dyv[j][i];
        DXh(i+2,j+2) = dxh[j][i];
	DYh(i+2,j+2) = dyh[j][i];
	DXu(i+2,j+2) = dxu[j][i];
	DYu(i+2,j+2) = dyu[j][i];
    }
    } */

//BX-a
  for (i=X0-1;i<=nx+2;i++)
    lonq[i] = WESTLON + LENLON*(double)(i-X0+X0abs)/(double)NXTOT;

  for (i=X0;i<=nx;i++)
    lonh[i] = WESTLON + LENLON*((double)(i-X0+X0abs)-0.5)/(double)NXTOT;
//BX-e
#endif


/* The remaining code should not be changed.                         */
  for (i=X0-1;i<=nx+2;i++) {
    for (j=Y0-1;j<=ny+2;j++) {
      IDXh(i,j) = (DXh(i,j) > 0.0) ? (1.0 / DXh(i,j)) : 0.0;
      IDXu(i,j) = (DXu(i,j) > 0.0) ? (1.0 / DXu(i,j)) : 0.0;
      IDXv(i,j) = (DXv(i,j) > 0.0) ? (1.0 / DXv(i,j)) : 0.0;
      IDXq(i,j) = (DXq(i,j) > 0.0) ? (1.0 / DXq(i,j)) : 0.0;
      IDYh(i,j) = (DYh(i,j) > 0.0) ? (1.0 / DYh(i,j)) : 0.0;
      IDYu(i,j) = (DYu(i,j) > 0.0) ? (1.0 / DYu(i,j)) : 0.0;
      IDYv(i,j) = (DYv(i,j) > 0.0) ? (1.0 / DYv(i,j)) : 0.0;
      IDYq(i,j) = (DYq(i,j) > 0.0) ? (1.0 / DYq(i,j)) : 0.0;

      //HF alternate def: DXDYh(i,j) = DXh(i,j) * DYh(i,j);
      //HF alternate def: IDXDYh(i,j) = IDXh(i,j) * IDYh(i,j);
      DXDYq(i,j) = DXq(i,j) * DYq(i,j);
      IDXDYq(i,j) = IDXq(i,j) * IDYq(i,j);

      Iareagr[i][j] = (areagr[i][j] > 0.0) ? (1.0 / areagr[i][j]) : 0.0;
      DXDYh(i,j) = areagr[i][j];
      IDXDYh(i,j) = Iareagr[i][j];
    }
  }

#endif /* CARTESIAN */
}