void get_grid_v1(int fid, double *xt, double *yt, double *xc, double *yc)
{
  int vid;
  
  vid = mpp_get_varid(fid, "grid_lon");
  mpp_get_var_value(fid, vid, xc);
  vid = mpp_get_varid(fid, "grid_lat");
  mpp_get_var_value(fid, vid, yc);
  vid = mpp_get_varid(fid, "grid_lont");
  mpp_get_var_value(fid, vid, xt);
  vid = mpp_get_varid(fid, "grid_latt");
  mpp_get_var_value(fid, vid, yt); 

}
void get_grid_v3(int fid, int nlon, int nlat, double *xt, double *yt, double *xc, double *yc)
{
  int vid, i, j;
  double *lon=NULL, *lat=NULL;
  double *lon_bnds=NULL, *lat_bnds=NULL;

  lon = (double *)malloc(nlon*sizeof(double));
  lat = (double *)malloc(nlat*sizeof(double));
  lon_bnds = (double *)malloc(2*nlon*sizeof(double));
  lat_bnds = (double *)malloc(2*nlat*sizeof(double));	 
  
  vid = mpp_get_varid(fid, "lon");
  mpp_get_var_value(fid, vid, lon);
  vid = mpp_get_varid(fid, "lat");
  mpp_get_var_value(fid, vid, lat);
  vid = mpp_get_varid(fid, "lon_bnds");
  mpp_get_var_value(fid, vid, lon_bnds);
  vid = mpp_get_varid(fid, "lat_bnds");
  mpp_get_var_value(fid, vid, lat_bnds);  

  for(j=0; j<nlat; j++) for(i=0; i<nlon; i++) {
    xt[j*nlon+i] = lon[i];
    yt[j*nlon+i] = lat[j];
  }
    
  for(j=0; j<nlat+1; j++) {
    for(i=0; i<nlon; i++) {
      xc[j*(nlon+1)+i] = lon_bnds[2*i];
    }
    xc[j*(nlon+1)+nlon] = lon_bnds[2*nlon-1];
  }

  for(i=0; i<nlon+1; i++) {
    for(j=0; j<nlat; j++) {
      yc[j*(nlon+1)+i] = lat_bnds[2*j];
    }
    yc[nlat*(nlon+1)+i] = lat_bnds[2*nlat-1];
  }

  free(lon);
  free(lat);
  free(lon_bnds);
  free(lat_bnds);
  
}
void get_grid_v2(int fid, int nlon, int nlat, double *xt, double *yt, double *xc, double *yc)
{
  int vid, i, j;
  double *x_vert=NULL, *y_vert=NULL;
  
  vid = mpp_get_varid(fid, "lon");
  mpp_get_var_value(fid, vid, xt);
  vid = mpp_get_varid(fid, "lat");
  mpp_get_var_value(fid, vid, yt);

  x_vert = (double *)malloc(nlon*nlat*4*sizeof(double));
  y_vert = (double *)malloc(nlon*nlat*4*sizeof(double));
  vid = mpp_get_varid(fid, "lon_vertices");
  mpp_get_var_value(fid, vid, x_vert);
  vid = mpp_get_varid(fid, "lat_vertices");
  mpp_get_var_value(fid, vid, y_vert);  

  for(j=0; j<nlat; j++) for(i=0; i<nlon; i++) {
    xc[j*(nlon+1)+i] = x_vert[(j*nlon+i)*4];
    yc[j*(nlon+1)+i] = y_vert[(j*nlon+i)*4];
  }

  for(j=0; j<nlat; j++) {
    xc[j*(nlon+1)+nlon] = x_vert[(j*nlon+nlon-1)*4+1];
    yc[j*(nlon+1)+nlon] = y_vert[(j*nlon+nlon-1)*4+1];
  }
      
  for(i=0; i<nlon; i++) {
    xc[nlat*(nlon+1)+i] = x_vert[((nlat-1)*nlon+i)*4+3];
    yc[nlat*(nlon+1)+i] = y_vert[((nlat-1)*nlon+i)*4+3];
  }

  xc[nlat*(nlon+1)+nlon] = x_vert[(nlat*nlon-1)*4+2];
  yc[nlat*(nlon+1)+nlon] = y_vert[(nlat*nlon-1)*4+2];

  free(x_vert);
  free(y_vert);
}
Exemple #4
0
main (int argc, char *argv[])
{
  
  extern char *optarg;
  char *pch=NULL, *dir=NULL, history[512], entry[1280];
  char tilefile[MAXTILE][STRING], tiletype[MAXTILE][SHORTSTRING];
  char tile_name[MAXTILE][STRING];
  int ntiles=0, nfiles=0, ncontact=0;
  int *nxp, *nyp;
  double **x, **y;
  double periodx=0, periody=0;
  int contact_tile1[MAXCONTACT], contact_tile2[MAXCONTACT];
  int contact_tile1_istart[MAXCONTACT], contact_tile1_iend[MAXCONTACT];
  int contact_tile1_jstart[MAXCONTACT], contact_tile1_jend[MAXCONTACT];
  int contact_tile2_istart[MAXCONTACT], contact_tile2_iend[MAXCONTACT];
  int contact_tile2_jstart[MAXCONTACT], contact_tile2_jend[MAXCONTACT];
  char mosaic_name[128] = "solo_mosaic";
  char grid_descriptor[128] = "";
  int c, i, n, m, l, errflg;
  
  int option_index = 0;
  static struct option long_options[] = {
    {"mosaic_name",     required_argument, NULL, 'm'},
    {"num_tiles",       required_argument, NULL, 'n'},
    {"grid_descriptor", required_argument, NULL, 'g'},
    {"tile_file",       required_argument, NULL, 'f'},  
    {"periodx",         required_argument, NULL, 'x'},
    {"periody",         required_argument, NULL, 'y'},
    {"directory",       required_argument, NULL, 'd'},
    {NULL, 0, NULL, 0}
  };

  mpp_init(&argc, &argv);
  /* this tool must be run one processor */
  if(mpp_npes()>1) mpp_error("make_solo_mosaic: this tool must be run on one processor");
  
  errflg = (argc == 1);
  /* First read command line arguments. */

  while ((c = getopt_long(argc, argv, "h", long_options, &option_index)) != -1) {
    switch (c) {
    case 'n':
      ntiles = atoi(optarg);
      break;
    case 'm':
      strcpy(mosaic_name, optarg);
      break;
    case 'g':
      strcpy(grid_descriptor, optarg);
      break;
    case 'f':
      strcpy(entry, optarg); 
      pch = strtok(entry, ", ");
      nfiles = 0;
      while( pch != NULL) {
        strcpy(tilefile[nfiles++], pch);
	pch = strtok(NULL, ", ");
      }
      break;
    case 'x':
      periodx = atof(optarg);
      break;
    case 'y':
      periody = atof(optarg);
      break; 
    case 'd':  // path of the simple grid file.
      dir = optarg;
      break;
    case '?':
      errflg++;
    }
  }

  if (errflg || ntiles < 1 || !dir ) {
    char **u = usage;
    while (*u) { fprintf(stderr, "%s\n", *u); u++; }
    exit(2);      
  }

  strcpy(history,argv[0]);

  for(i=1;i<argc;i++) {
    strcat(history, " ");
    strcat(history, argv[i]);
  }

  if(ntiles > MAXTILE) {
    mpp_error("make_solo_mosaic: number of tiles is greater than MAXTILE.");
  }
    
  /*--- if file name is not specified through -f, file name will be horizontal_grid.tile#.nc */
  if(nfiles == 0) {
    if(ntiles == 1) {
      sprintf(tilefile[0],"horizontal_grid.nc");
    }
    else {
      for(n=0; n<ntiles; n++) {
	sprintf(tilefile[n],"horizontal_grid.tile%d.nc",n+1);
      }
    }
  }
  else { /* Check if ntile are matching number of grid file passed through -f */
    if( nfiles != ntiles) mpp_error("make_solo_mosaic: number of grid files specified through -n "
				   " does not equal to number of files specified through -f = ");
  }

  n = strlen(dir);
  if( dir[n-1] != '/') strcat(dir, "/");

  /*First read all the grid files.*/
  nxp = (int *)malloc(ntiles*sizeof(int));
  nyp = (int *)malloc(ntiles*sizeof(int));
  x = (double **)malloc(ntiles*sizeof(double *));
  y = (double **)malloc(ntiles*sizeof(double *));
  for(n=0; n<ntiles; n++) {
    char filepath[512];
    int fid, vid;
    sprintf(filepath, "%s%s",dir, tilefile[n]);
    fid = mpp_open(filepath, MPP_READ);
    nxp[n] = mpp_get_dimlen(fid, "nxp");
    nyp[n] = mpp_get_dimlen(fid, "nyp");
    x[n] = (double *)malloc(nxp[n]*nyp[n]*sizeof(double));
    y[n] = (double *)malloc(nxp[n]*nyp[n]*sizeof(double));
    vid = mpp_get_varid(fid, "tile");
    mpp_get_var_value(fid, vid, tile_name[n]);
    vid = mpp_get_varid(fid, "x");
    mpp_get_var_value(fid, vid, x[n]);
    vid = mpp_get_varid(fid, "y");
    mpp_get_var_value(fid, vid, y[n]);
    mpp_close(fid);
  }


  /*find the contact region between tiles, currently assume the contact region are align-contact
    There should be no contact between same directions of two tiles ( w-w, e-e, s-s, n-n)
    We assume no contact between w-s, e-n ( will added in if needed ) . */
  ncontact = 0;
  for(n=0; n<ntiles; n++) {
    for(m=n; m<ntiles; m++) {
      int count;
      int istart1[MAXCONTACT], iend1[MAXCONTACT], jstart1[MAXCONTACT], jend1[MAXCONTACT];
      int istart2[MAXCONTACT], iend2[MAXCONTACT], jstart2[MAXCONTACT], jend2[MAXCONTACT];
      count = get_align_contact(n+1, m+1, nxp[n], nyp[n], nxp[m], nyp[m], x[n], y[n], x[m], y[m],
				periodx, periody, istart1, iend1, jstart1, jend1, istart2, iend2,
				jstart2, jend2);
      if(ncontact+count>MAXCONTACT) mpp_error("make_solo_mosaic: number of contacts is more than MAXCONTACT 1");
      for(l=0; l<count; l++) {
	contact_tile1_istart[ncontact] = istart1[l];
	contact_tile1_iend  [ncontact] = iend1[l];
	contact_tile1_jstart[ncontact] = jstart1[l];
	contact_tile1_jend  [ncontact] = jend1[l];
	contact_tile2_istart[ncontact] = istart2[l];
	contact_tile2_iend  [ncontact] = iend2[l];
	contact_tile2_jstart[ncontact] = jstart2[l];
	contact_tile2_jend  [ncontact] = jend2[l];
	contact_tile1       [ncontact] = n;
	contact_tile2       [ncontact] = m;
	ncontact++;
      }
    }
  }

  for(n=0; n<ntiles; n++) {
    for(m=n+1; m<ntiles; m++) {
      int count;
      int istart1[MAXCONTACT], iend1[MAXCONTACT], jstart1[MAXCONTACT], jend1[MAXCONTACT];
      int istart2[MAXCONTACT], iend2[MAXCONTACT], jstart2[MAXCONTACT], jend2[MAXCONTACT];
      count = get_overlap_contact(n+1, m+1, nxp[n], nyp[n], nxp[m], nyp[m], x[n], y[n], x[m], y[m],
				  istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2);
      if(ncontact+count>MAXCONTACT) mpp_error("make_solo_mosaic: number of contacts is more than MAXCONTACT 2");
      for(l=0; l<count; l++) {
	contact_tile1_istart[ncontact] = istart1[l];
	contact_tile1_iend  [ncontact] = iend1[l];
	contact_tile1_jstart[ncontact] = jstart1[l];
	contact_tile1_jend  [ncontact] = jend1[l];
	contact_tile2_istart[ncontact] = istart2[l];
	contact_tile2_iend  [ncontact] = iend2[l];
	contact_tile2_jstart[ncontact] = jstart2[l];
	contact_tile2_jend  [ncontact] = jend2[l];
	contact_tile1       [ncontact] = n;
	contact_tile2       [ncontact] = m;
	ncontact++;
      }
    }
  }
  

  /* write out data */
  {
    char str[STRING], outfile[STRING];
    int fid, dim_ntiles, dim_ncontact, dim_string, id_mosaic, id_gridtiles, id_contacts;
    int id_contact_index, id_griddir, id_gridfiles, dim[2];
    size_t start[4], nwrite[4];

    sprintf(outfile, "%s.nc", mosaic_name);
    fid = mpp_open(outfile, MPP_WRITE);
    /* define dimenison */
    dim_ntiles = mpp_def_dim(fid, "ntiles", ntiles);
    if(ncontact>0) dim_ncontact = mpp_def_dim(fid, "ncontact", ncontact);
    dim_string = mpp_def_dim(fid, "string", STRING);    
    /* define variable */
    id_mosaic = mpp_def_var(fid, "mosaic", MPP_CHAR, 1, &dim_string, 4, "standard_name",
			    "grid_mosaic_spec", "children", "gridtiles", "contact_regions", "contacts",
			    "grid_descriptor", grid_descriptor);
    dim[0] = dim_ntiles; dim[1] = dim_string;
    id_griddir   = mpp_def_var(fid, "gridlocation", MPP_CHAR, 1, &dim[1], 1,
			       "standard_name", "grid_file_location");
    id_gridfiles = mpp_def_var(fid, "gridfiles", MPP_CHAR, 2, dim, 0);
    id_gridtiles = mpp_def_var(fid, "gridtiles", MPP_CHAR, 2, dim, 0);

    if(ncontact>0) {
      dim[0] = dim_ncontact; dim[1] = dim_string;
      id_contacts = mpp_def_var(fid, "contacts", MPP_CHAR, 2, dim, 5, "standard_name", "grid_contact_spec",
				"contact_type", "boundary", "alignment", "true",
				"contact_index", "contact_index", "orientation", "orient");
      id_contact_index = mpp_def_var(fid, "contact_index", MPP_CHAR, 2, dim, 1, "standard_name",
				     "starting_ending_point_index_of_contact");

    }
    mpp_def_global_att(fid, "grid_version", grid_version);
    mpp_def_global_att(fid, "code_version", tagname);
    mpp_def_global_att(fid, "history", history);
    mpp_end_def(fid);

    /* write out data */
    for(i=0; i<4; i++) {
      start[i] = 0; nwrite[i] = 1;
    }
    nwrite[0] = strlen(mosaic_name);
    mpp_put_var_value_block(fid, id_mosaic, start, nwrite, mosaic_name);
    nwrite[0] = strlen(dir);
    mpp_put_var_value_block(fid, id_griddir, start, nwrite, dir);
    nwrite[0] = 1;
    for(n=0; n<ntiles; n++) {
      start[0] = n; nwrite[1] = strlen(tile_name[n]);
      mpp_put_var_value_block(fid, id_gridtiles, start, nwrite, tile_name[n]);
      nwrite[1] = strlen(tilefile[n]);
      mpp_put_var_value_block(fid, id_gridfiles, start, nwrite, tilefile[n]);
    }
    
    for(n=0; n<ncontact; n++) {
      sprintf(str,"%s:%s::%s:%s", mosaic_name, tile_name[contact_tile1[n]], mosaic_name,
	      tile_name[contact_tile2[n]]);
      start[0] = n; nwrite[1] = strlen(str);
      mpp_put_var_value_block(fid, id_contacts, start, nwrite, str);
      sprintf(str,"%d:%d,%d:%d::%d:%d,%d:%d", contact_tile1_istart[n], contact_tile1_iend[n],
	      contact_tile1_jstart[n], contact_tile1_jend[n], contact_tile2_istart[n],
	      contact_tile2_iend[n], contact_tile2_jstart[n], contact_tile2_jend[n] );
      nwrite[1] = strlen(str);
      mpp_put_var_value_block(fid, id_contact_index, start, nwrite, str);
    }
    mpp_close(fid);    
  }

  
  printf("congradulation: You have successfully run make_solo_mosaic\n");

  return 0;
  
}; // end of main
int main (int argc, char *argv[])
{
  int c, n, i;
  int errflg = (argc == 1);
  int    option_index = 0;
  int fid, vid, nfile_aXl, ntiles;

  int *nx, *ny;
  double **lonb, **latb, **land_area, **ocean_area, **cell_area;
  char **axl_file = NULL, **axo_file=NULL, **lxo_file=NULL;
  char **ocn_topog_file = NULL;
  char *input_mosaic = NULL;
  char mosaic_name[STRING] = "mosaic", mosaic_file[STRING];
  char griddir[STRING], lnd_mosaic[STRING], filepath[STRING];
  char history[512];
  
  static struct option long_options[] = {
    {"input_mosaic",       required_argument, NULL, 'i'},
    {"mosaic_name",        required_argument, NULL, 'm'},
    {NULL, 0, NULL, 0}
  };

  
  /*
   * process command line
   */

  while ((c = getopt_long(argc, argv, "i:", long_options, &option_index) ) != -1)
    switch (c) {
    case 'i': 
      input_mosaic = optarg;
      break;
    case 'm':
      strcpy(mosaic_name,optarg);
      break;
        case '?':
      errflg++;
    }
  if (errflg || !input_mosaic)  {
    char **u = usage;
    while (*u) { fprintf(stderr, "%s\n", *u); u++; }
    exit(2);
  }  

  strcpy(history,argv[0]);

  for(i=1;i<argc;i++) {
    strcat(history, " ");
    strcat(history, argv[i]);
  }
  
  /* First get land grid information */
  
  mpp_init(&argc, &argv);
  sprintf(mosaic_file, "%s.nc", mosaic_name);
  get_file_path(input_mosaic, griddir);  
  fid = mpp_open(input_mosaic, MPP_READ);
  vid = mpp_get_varid(fid, "lnd_mosaic_file");
  mpp_get_var_value(fid, vid, lnd_mosaic);
  nfile_aXl = mpp_get_dimlen( fid, "nfile_aXl");

  /*make sure the directory that stores the mosaic_file is not current directory */
  { 
    char cur_path[STRING];
    
    if(getcwd(cur_path, STRING) != cur_path ) mpp_error("make_quick_mosaic: The size of cur_path maybe is not big enough");
    printf("The current directory is %s\n", cur_path);
    printf("The mosaic file location is %s\n", griddir);
    if(strcmp(griddir, cur_path)==0 || strcmp( griddir, ".")==0)
      mpp_error("make_quick_mosaic: The input mosaic file location should not be current directory");
  }
  
  sprintf(filepath, "%s/%s", griddir, lnd_mosaic);
  ntiles = read_mosaic_ntiles(filepath);
  /* copy the lnd_mosaic file and grid file */
  {
    int fid2, vid2;
    char cmd[STRING], gridfile[STRING];
    size_t start[4], nread[4];
    sprintf(cmd, "cp %s %s", filepath, lnd_mosaic);

    system(cmd);
    fid2 = mpp_open(filepath, MPP_READ);
    vid2 = mpp_get_varid(fid2, "gridfiles");
    for(i=0; i<4; i++) {
      start[i] = 0; nread[i] = 1;
    }	  
    for(n=0; n<ntiles; n++) {  
      start[0] = n; nread[1] = STRING;
      mpp_get_var_value_block(fid2, vid2, start, nread, gridfile);
      sprintf(cmd, "cp %s/%s %s", griddir, gridfile, gridfile);
      printf("%s \n", cmd);
      system(cmd);
    }
    mpp_close(fid2);
  }

  /* ntiles should be either 1 or ntiles = nfile_aXl */
  if(ntiles != nfile_aXl && ntiles != 1)
    mpp_error("make_quick_mosaic: only support ntiles = 1 or ntiles = nfile_aXl, contact developer");

  nx = (int *)malloc(ntiles*sizeof(int));
  ny = (int *)malloc(ntiles*sizeof(int));
  read_mosaic_grid_sizes(filepath, nx, ny);
  lonb = (double **)malloc(ntiles*sizeof(double *));
  latb = (double **)malloc(ntiles*sizeof(double *));
  for(n=0; n<ntiles; n++) {
     lonb[n] = (double *)malloc((nx[n]+1)*(ny[n]+1)*sizeof(double));
     latb[n] = (double *)malloc((nx[n]+1)*(ny[n]+1)*sizeof(double));     
     read_mosaic_grid_data(filepath, "x", nx[n], ny[n], lonb[n], n, 0, 0); 
     read_mosaic_grid_data(filepath, "y", nx[n], ny[n], latb[n], n, 0, 0);
     for(i=0; i<(nx[n]+1)*(ny[n]+1); i++) {
       lonb[n][i] *= (M_PI/180.0);
       latb[n][i] *= (M_PI/180.0);
     }
  }

  
  /* read the exchange grid information and get the land/sea mask of land model*/
  land_area = (double **)malloc(ntiles*sizeof(double *));
  for(n=0; n<ntiles; n++) {
    land_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double));
    for(i=0; i<nx[n]*ny[n]; i++) land_area[n][i] = 0;
  }

  vid = mpp_get_varid(fid, "aXl_file");
  for(n=0; n<nfile_aXl; n++) {
    size_t start[4], nread[4];
    int nxgrid;
    char aXl_file[STRING];
    start[0] = n;
    start[1] = 0;
    nread[0] = 1;
    nread[1] = STRING;
    mpp_get_var_value_block(fid, vid, start, nread, aXl_file);
    sprintf(filepath, "%s/%s", griddir, aXl_file);
    nxgrid = read_mosaic_xgrid_size(filepath);
    if(nxgrid>0) {
      int l;
      int *i1, *j1, *i2, *j2;
      double *area;

      i1 = (int *)malloc(nxgrid*sizeof(int));
      j1 = (int *)malloc(nxgrid*sizeof(int));
      i2 = (int *)malloc(nxgrid*sizeof(int));
      j2 = (int *)malloc(nxgrid*sizeof(int));
      area = (double *)malloc(nxgrid*sizeof(double));
      read_mosaic_xgrid_order1(filepath, i1, j1, i2, j2, area);
      if(ntiles == 1) {
	for(l=0; l<nxgrid; l++) land_area[0][j2[l]*nx[0]+i2[l]] += (area[l]*4*M_PI*RADIUS*RADIUS);
      }
      else {
	for(l=0; l<nxgrid; l++) land_area[n][j2[l]*nx[n]+i2[l]] += (area[l]*4*M_PI*RADIUS*RADIUS);
      }
      free(i1);
      free(j1);
      free(i2);
      free(j2);
      free(area);
    }
  }

  mpp_close(fid);
  
  /* calculate ocean area */
  ocean_area = (double **)malloc(ntiles*sizeof(double *));
  cell_area = (double **)malloc(ntiles*sizeof(double *));
  for(n=0; n<ntiles; n++) {
    ocean_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double));
    cell_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double));
    get_grid_area(&nx[n], &ny[n], lonb[n], latb[n], cell_area[n]);
    for(i=0; i<nx[n]*ny[n]; i++) {
      ocean_area[n][i] = cell_area[n][i];
      if( fabs(ocean_area[n][i]-land_area[n][i])/ocean_area[n][i] < AREA_RATIO_THRESH )
	ocean_area[n][i] = 0;
      else 
	ocean_area[n][i] -= land_area[n][i];
      if(ocean_area[n][i] < 0) {
	printf("at i = %d, ocean_area = %g, land_area = %g, cell_area=%g\n", i, ocean_area[n][i], land_area[n][i], cell_area[n][i]);
	mpp_error("make_quick_mosaic: ocean area is negative at some points");
      }
    }
  }

  /* write out land mask */
  {
    for(n=0; n<ntiles; n++) {
      int fid, id_mask, dims[2];
      char lnd_mask_file[STRING];
      double *mask;
      mask = (double *)malloc(nx[n]*ny[n]*sizeof(double));
      for(i=0; i<nx[n]*ny[n]; i++) mask[i] = land_area[n][i]/cell_area[n][i];
      
      if(ntiles > 1)
	sprintf(lnd_mask_file, "land_mask_tile%d.nc", n+1);
      else
	strcpy(lnd_mask_file, "land_mask.nc");
      fid = mpp_open(lnd_mask_file, MPP_WRITE);
      mpp_def_global_att(fid, "grid_version", grid_version);
      mpp_def_global_att(fid, "code_version", tagname);
      mpp_def_global_att(fid, "history", history);
      dims[1] = mpp_def_dim(fid, "nx", nx[n]); 
      dims[0] = mpp_def_dim(fid, "ny", ny[n]);
      id_mask = mpp_def_var(fid, "mask", MPP_DOUBLE, 2, dims,  2, "standard_name",
			    "land fraction at T-cell centers", "units", "none");
      mpp_end_def(fid);
      mpp_put_var_value(fid, id_mask, mask);
      free(mask);
      mpp_close(fid);
    }
  }
    
  /* write out ocean mask */
  {
    for(n=0; n<ntiles; n++) {
      int fid, id_mask, dims[2];
      char ocn_mask_file[STRING];
      double *mask;
      mask = (double *)malloc(nx[n]*ny[n]*sizeof(double));
      for(i=0; i<nx[n]*ny[n]; i++) mask[i] = ocean_area[n][i]/cell_area[n][i];
      
      if(ntiles > 1)
	sprintf(ocn_mask_file, "ocean_mask_tile%d.nc", n+1);
      else
	strcpy(ocn_mask_file, "ocean_mask.nc");
      fid = mpp_open(ocn_mask_file, MPP_WRITE);
      mpp_def_global_att(fid, "grid_version", grid_version);
      mpp_def_global_att(fid, "code_version", tagname);
      mpp_def_global_att(fid, "history", history);
      dims[1] = mpp_def_dim(fid, "nx", nx[n]); 
      dims[0] = mpp_def_dim(fid, "ny", ny[n]);
      id_mask = mpp_def_var(fid, "mask", MPP_DOUBLE, 2, dims,  2, "standard_name",
			    "ocean fraction at T-cell centers", "units", "none");
      mpp_end_def(fid);
      mpp_put_var_value(fid, id_mask, mask);
      free(mask);
      mpp_close(fid);
    }
  }
  
  ocn_topog_file = (char **)malloc(ntiles*sizeof(char *));
  axl_file = (char **)malloc(ntiles*sizeof(char *));
  axo_file = (char **)malloc(ntiles*sizeof(char *));
  lxo_file = (char **)malloc(ntiles*sizeof(char *));
  for(n=0; n<ntiles; n++) {
    axl_file[n] = (char *)malloc(STRING*sizeof(char));
    axo_file[n] = (char *)malloc(STRING*sizeof(char));
    lxo_file[n] = (char *)malloc(STRING*sizeof(char));
    ocn_topog_file[n] = (char *)malloc(STRING*sizeof(char));
    sprintf(ocn_topog_file[n], "ocean_topog_tile%d.nc", n+1);
    sprintf(axl_file[n], "atmos_mosaic_tile%dXland_mosaic_tile%d.nc", n+1, n+1);
    sprintf(axo_file[n], "atmos_mosaic_tile%dXocean_mosaic_tile%d.nc", n+1, n+1);
    sprintf(lxo_file[n], "land_mosaic_tile%dXocean_mosaic_tile%d.nc", n+1, n+1);
  }
  
  
  for(n=0; n<ntiles; n++) {
    int *i1, *j1, *i2, *j2;
    double *area, *di, *dj;
    int nxgrid, i, j;
    int fid, dim_string, dim_ncells, dim_two, dims[2];
    int id_contact, id_tile1_cell, id_tile2_cell;
    int id_xgrid_area, id_tile1_dist, id_tile2_dist;
    size_t start[4], nwrite[4];
    char contact[STRING];

    for(i=0; i<4; i++) {
      start[i] = 0; nwrite[i] = 1;
    }	  
    
    /* first calculate the atmXlnd exchange grid */
    i1 = (int *)malloc(nx[n]*ny[n]*sizeof(int));
    j1 = (int *)malloc(nx[n]*ny[n]*sizeof(int));
    i2 = (int *)malloc(nx[n]*ny[n]*sizeof(int));
    j2 = (int *)malloc(nx[n]*ny[n]*sizeof(int));
    area = (double *)malloc(nx[n]*ny[n]*sizeof(double));
    di   = (double *)malloc(nx[n]*ny[n]*sizeof(double));
    dj   = (double *)malloc(nx[n]*ny[n]*sizeof(double));

    /* write out the atmosXland exchange grid file, The file name will be atmos_mosaic_tile#Xland_mosaic_tile#.nc */   
    nxgrid = 0;
    for(j=0; j<ny[n]; j++) for(i=0; i<nx[n]; i++) {
      if(land_area[n][j*nx[n]+i] >0) {
	i1[nxgrid] = i+1;
	j1[nxgrid] = j+1;
	i2[nxgrid] = i+1;
	j2[nxgrid] = j+1;
	area[nxgrid] = land_area[n][j*nx[n]+i];
	di[nxgrid] = 0;
	dj[nxgrid] = 0;
	nxgrid++;
      }
    }
 
    fid = mpp_open(axl_file[n], MPP_WRITE);
    sprintf(contact, "atmos_mosaic:tile%d::land_mosaic:tile%d", n+1, n+1);
    mpp_def_global_att(fid, "grid_version", grid_version);
    mpp_def_global_att(fid, "code_version", tagname);
    mpp_def_global_att(fid, "history", history);
    dim_string = mpp_def_dim(fid, "string", STRING);
    dim_ncells = mpp_def_dim(fid, "ncells", nxgrid);
    dim_two    = mpp_def_dim(fid, "two", 2);
    id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec",
			     "contact_type", "exchange", "parent1_cell",
			     "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", 
			     "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance");
	    
    dims[0] = dim_ncells; dims[1] = dim_two;
    id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1");
    id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2");
    id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name",
				"exchange_grid_area", "units", "m2");
    id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid");
    id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid");
    mpp_end_def(fid);
    nwrite[0] = strlen(contact);
    mpp_put_var_value_block(fid, id_contact, start, nwrite, contact);
    nwrite[0] = nxgrid;
    mpp_put_var_value(fid, id_xgrid_area, area);
    mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1);
    mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2);
    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di);
    mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di);    
    start[1] = 1;
    mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1);
    mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2);
    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj);
    mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj);   
    mpp_close(fid);
    
    /* write out the atmosXocean exchange grid file, The file name will be atmos_mosaic_tile#Xocean_mosaic_tile#.nc */
    nxgrid = 0;
    for(j=0; j<ny[n]; j++) for(i=0; i<nx[n]; i++) {
      if(ocean_area[n][j*nx[n]+i] >0) {
	i1[nxgrid] = i+1;
	j1[nxgrid] = j+1;
	i2[nxgrid] = i+1;
	j2[nxgrid] = j+1;
	area[nxgrid] = ocean_area[n][j*nx[n]+i];
	di[nxgrid] = 0;
	dj[nxgrid] = 0;
	nxgrid++;
      }
    }    
    fid = mpp_open(axo_file[n], MPP_WRITE);
    sprintf(contact, "atmos_mosaic:tile%d::ocean_mosaic:tile%d", n+1, n+1);
    mpp_def_global_att(fid, "grid_version", grid_version);
    mpp_def_global_att(fid, "code_version", tagname);
    mpp_def_global_att(fid, "history", history);
    dim_string = mpp_def_dim(fid, "string", STRING);
    dim_ncells = mpp_def_dim(fid, "ncells", nxgrid);
    dim_two    = mpp_def_dim(fid, "two", 2);
    id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec",
			     "contact_type", "exchange", "parent1_cell",
			     "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", 
			     "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance");
	    
    dims[0] = dim_ncells; dims[1] = dim_two;
    id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1");
    id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2");
    id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name",
				"exchange_grid_area", "units", "m2");
    id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid");
    id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid");
    mpp_end_def(fid);
    start[1] = 0;
    nwrite[0] = strlen(contact);
    mpp_put_var_value_block(fid, id_contact, start, nwrite, contact);
    nwrite[0] = nxgrid;
    mpp_put_var_value(fid, id_xgrid_area, area);
    mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1);
    mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2);
    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di);
    mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di);    
    start[1] = 1;
    mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1);
    mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2);
    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj);
    mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj);   
    mpp_close(fid);
    
    /* write out landXocean exchange grid information */
    fid = mpp_open(lxo_file[n], MPP_WRITE);
    sprintf(contact, "land_mosaic:tile%d::ocean_mosaic:tile%d", n+1, n+1);
    mpp_def_global_att(fid, "grid_version", grid_version);
    mpp_def_global_att(fid, "code_version", tagname);
    mpp_def_global_att(fid, "history", history);
    dim_string = mpp_def_dim(fid, "string", STRING);
    dim_ncells = mpp_def_dim(fid, "ncells", nxgrid);
    dim_two    = mpp_def_dim(fid, "two", 2);
    id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec",
			     "contact_type", "exchange", "parent1_cell",
			     "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", 
			     "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance");
	    
    dims[0] = dim_ncells; dims[1] = dim_two;
    id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1");
    id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2");
    id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name",
				"exchange_grid_area", "units", "m2");
    id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid");
    id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid");
    mpp_end_def(fid);
    start[1] = 0;
    nwrite[0] = strlen(contact);
    mpp_put_var_value_block(fid, id_contact, start, nwrite, contact);
    nwrite[0] = nxgrid;
    mpp_put_var_value(fid, id_xgrid_area, area);
    mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1);
    mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2);
    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di);
    mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di);    
    start[1] = 1;
    mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1);
    mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2);
    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj);
    mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj);   
    mpp_close(fid);
    
    free(i1);
    free(j1);
    free(i2);
    free(j2);
    free(area);
    free(di);
    free(dj);
  }
  
  /*Fianlly create the coupler mosaic file mosaic_name.nc */
  {
    int dim_string, dim_axo, dim_axl, dim_lxo, dims[2];
    int id_amosaic_file, id_lmosaic_file, id_omosaic_file, id_otopog_file;
    int id_axo_file, id_axl_file, id_lxo_file;
    size_t start[4], nwrite[4];

    for(i=0; i<4; i++) {
      start[i] = 0; nwrite[i] = 1;
    }	      
    printf("mosaic_file is %s\n", mosaic_file);   
    fid = mpp_open(mosaic_file, MPP_WRITE);
    mpp_def_global_att(fid, "grid_version", grid_version);
    mpp_def_global_att(fid, "code_version", tagname);
    mpp_def_global_att(fid, "history", history);
    dim_string = mpp_def_dim(fid, "string", STRING);
    dim_axo = mpp_def_dim(fid, "nfile_aXo", ntiles);
    dim_axl = mpp_def_dim(fid, "nfile_aXl", ntiles);
    dim_lxo = mpp_def_dim(fid, "nfile_lXo", ntiles);    
    id_amosaic_file = mpp_def_var(fid, "atm_mosaic_file", MPP_CHAR, 1, &dim_string,
				  1, "standard_name", "atmosphere_mosaic_file_name");
    id_lmosaic_file = mpp_def_var(fid, "lnd_mosaic_file", MPP_CHAR, 1, &dim_string,
				  1, "standard_name", "land_mosaic_file_name");
    id_omosaic_file = mpp_def_var(fid, "ocn_mosaic_file", MPP_CHAR, 1, &dim_string,
				  1, "standard_name", "ocean_mosaic_file_name");
    id_otopog_file  = mpp_def_var(fid, "ocn_topog_file", MPP_CHAR, 1, &dim_string,
				  1, "standard_name", "ocean_topog_file_name");    
    dims[0] = dim_axo; dims[1] = dim_string;
    id_axo_file = mpp_def_var(fid, "aXo_file", MPP_CHAR, 2, dims, 1, "standard_name", "atmXocn_exchange_grid_file");
    dims[0] = dim_axl; dims[1] = dim_string;
    id_axl_file = mpp_def_var(fid, "aXl_file", MPP_CHAR, 2, dims, 1, "standard_name", "atmXlnd_exchange_grid_file");
    dims[0] = dim_lxo; dims[1] = dim_string;
    id_lxo_file = mpp_def_var(fid, "lXo_file", MPP_CHAR, 2, dims, 1, "standard_name", "lndXocn_exchange_grid_file");
    mpp_end_def(fid);    
    nwrite[0] = strlen(lnd_mosaic);
    mpp_put_var_value_block(fid, id_lmosaic_file, start, nwrite, lnd_mosaic);
    mpp_put_var_value_block(fid, id_amosaic_file, start, nwrite, lnd_mosaic);
    mpp_put_var_value_block(fid, id_omosaic_file, start, nwrite, lnd_mosaic);
    for(n=0; n<ntiles; n++) {
      start[0] = n; nwrite[0] =1;
      nwrite[1] = strlen(ocn_topog_file[n]);
      mpp_put_var_value_block(fid, id_otopog_file, start, nwrite, ocn_topog_file[n]);
      nwrite[1] = strlen(axl_file[n]);
      mpp_put_var_value_block(fid, id_axl_file, start, nwrite, axl_file[n]);
      nwrite[1] = strlen(axo_file[n]);
      mpp_put_var_value_block(fid, id_axo_file, start, nwrite, axo_file[n]);
      nwrite[1] = strlen(lxo_file[n]);
      mpp_put_var_value_block(fid, id_lxo_file, start, nwrite, lxo_file[n]);
    }
    mpp_close(fid);
  }
    
  for(n=0; n<ntiles; n++) {
    free(axl_file[n]);
    free(axo_file[n]);
    free(lxo_file[n]);
  }
  free(axl_file);
  free(axo_file);
  free(lxo_file);
  printf("\n***** Congratulation! You have successfully run make_quick_mosaic\n");
  mpp_end();

  return 0;

} /* main */  
Exemple #6
0
/*******************************************************************************
  void setup_conserve_interp
  Setup the interpolation weight for conservative interpolation 
*******************************************************************************/
void setup_conserve_interp(int ntiles_in, const Grid_config *grid_in, int ntiles_out,
			   Grid_config *grid_out, Interp_config *interp, unsigned int opcode) 
{
  int    n, m, i, ii, jj, nx_in, ny_in, nx_out, ny_out, tile;
  size_t nxgrid, nxgrid2, nxgrid_prev;
  int    *i_in, *j_in, *i_out, *j_out;
  int   *tmp_t_in, *tmp_i_in, *tmp_j_in, *tmp_i_out, *tmp_j_out;
  double *tmp_di_in, *tmp_dj_in;
  double *xgrid_area, *tmp_area, *xgrid_clon, *xgrid_clat;
  
  double garea;
  typedef struct{
    double *area;
    double *clon;
    double *clat;
  } CellStruct;
  CellStruct *cell_in;
  
  i_in       = (int    *)malloc(MAXXGRID   * sizeof(int   ));
  j_in       = (int    *)malloc(MAXXGRID   * sizeof(int   ));
  i_out      = (int    *)malloc(MAXXGRID   * sizeof(int   ));
  j_out      = (int    *)malloc(MAXXGRID   * sizeof(int   ));
  xgrid_area = (double *)malloc(MAXXGRID   * sizeof(double));
  if(opcode & CONSERVE_ORDER2) {
    xgrid_clon = (double *)malloc(MAXXGRID   * sizeof(double));
    xgrid_clat = (double *)malloc(MAXXGRID   * sizeof(double));
  }
  garea = 4*M_PI*RADIUS*RADIUS;
  
  if( opcode & READ) {
    for(n=0; n<ntiles_out; n++) {
      if( interp[n].file_exist ) { /* reading from file */
	int *t_in, *ind;
	int fid, vid;
	
	nxgrid     = read_mosaic_xgrid_size(interp[n].remap_file);
	t_in       = (int    *)malloc(nxgrid*sizeof(int   ));
	ind        = (int    *)malloc(nxgrid*sizeof(int   ));
	if(opcode & CONSERVE_ORDER1)
	  read_mosaic_xgrid_order1(interp[n].remap_file, i_in, j_in, i_out, j_out, xgrid_area);
	else
	  read_mosaic_xgrid_order2(interp[n].remap_file, i_in, j_in, i_out, j_out, xgrid_area, xgrid_clon, xgrid_clat);
	
	/*--- rescale the xgrid area */
	for(i=0; i<nxgrid; i++) xgrid_area[i] *= garea;
	fid = mpp_open(interp[n].remap_file, MPP_READ);
	vid = mpp_get_varid(fid, "tile1");
      	mpp_get_var_value(fid, vid, t_in);
	mpp_close(fid);
	/*distribute the exchange grid on each pe according to target grid index*/
	interp[n].nxgrid = 0;
	for(i=0; i<nxgrid; i++) {
	  if( i_out[i] <= grid_out[n].iec && i_out[i] >= grid_out[n].isc &&
	      j_out[i] <= grid_out[n].jec && j_out[i] >= grid_out[n].jsc )
	    ind[interp[n].nxgrid++] = i;
	}
	interp[n].i_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	interp[n].j_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	interp[n].i_out  = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	interp[n].j_out  = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	interp[n].area   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	interp[n].t_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));

	for(i=0; i< interp[n].nxgrid; i++) {
	  interp[n].i_in [i] = i_in [ind[i]];
	  interp[n].j_in [i] = j_in [ind[i]];
	  interp[n].t_in [i] = t_in [ind[i]] - 1;
	  interp[n].i_out[i] = i_out[ind[i]] - grid_out[n].isc;
	  interp[n].j_out[i] = j_out[ind[i]] - grid_out[n].jsc;
	  interp[n].area [i] = xgrid_area[ind[i]];
     	}
	if(opcode & CONSERVE_ORDER2) {
	  interp[n].di_in   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	  interp[n].dj_in   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	  for(i=0; i< interp[n].nxgrid; i++) {
	    interp[n].di_in[i] = xgrid_clon[ind[i]];
	    interp[n].dj_in[i] = xgrid_clat[ind[i]];
	  }
	}	
	free(t_in);
	free(ind);
      }
    }
    if(mpp_pe() == mpp_root_pe())printf("NOTE: Finish reading index and weight for conservative interpolation from file.\n");
  }
  else {
    cell_in    = (CellStruct *)malloc(ntiles_in * sizeof(CellStruct));
    for(m=0; m<ntiles_in; m++) {
      nx_in = grid_in[m].nx;
      ny_in = grid_in[m].ny;
      cell_in[m].area = (double *)malloc(nx_in*ny_in*sizeof(double));
      cell_in[m].clon = (double *)malloc(nx_in*ny_in*sizeof(double));
      cell_in[m].clat = (double *)malloc(nx_in*ny_in*sizeof(double));
      for(n=0; n<nx_in*ny_in; n++) {
	cell_in[m].area[n] = 0;
	cell_in[m].clon[n] = 0;
        cell_in[m].clat[n] = 0;
      }
    }
    for(n=0; n<ntiles_out; n++) {
      nx_out    = grid_out[n].nxc;
      ny_out    = grid_out[n].nyc;      
      interp[n].nxgrid = 0;
      for(m=0; m<ntiles_in; m++) {
	double *mask;
        nx_in = grid_in[m].nx;
	ny_in = grid_in[m].ny;

	mask = (double *)malloc(nx_in*ny_in*sizeof(double));
	for(i=0; i<nx_in*ny_in; i++) mask[i] = 1.0; 
	
	if(opcode & CONSERVE_ORDER1) {
	  nxgrid = create_xgrid_2dx2d_order1(&nx_in, &ny_in, &nx_out, &ny_out, grid_in[m].lonc,
					     grid_in[m].latc,  grid_out[n].lonc,  grid_out[n].latc,
					     mask, i_in, j_in, i_out, j_out, xgrid_area);
	}
	else if(opcode & CONSERVE_ORDER2) {
	  int g_nxgrid;
	  int    *g_i_in, *g_j_in;
	  double *g_area, *g_clon, *g_clat;
	  
	  nxgrid = create_xgrid_2dx2d_order2(&nx_in, &ny_in, &nx_out, &ny_out, grid_in[m].lonc,
					     grid_in[m].latc,  grid_out[n].lonc,  grid_out[n].latc,
					     mask, i_in, j_in, i_out, j_out, xgrid_area, xgrid_clon, xgrid_clat);
	  /* For the purpose of bitiwise reproducing, the following operation is needed. */
      	  g_nxgrid = nxgrid;
	  mpp_sum_int(1, &g_nxgrid);
	  if(g_nxgrid > 0) {
	    g_i_in = (int    *)malloc(g_nxgrid*sizeof(int   ));
	    g_j_in = (int    *)malloc(g_nxgrid*sizeof(int   ));			   
	    g_area = (double *)malloc(g_nxgrid*sizeof(double));
	    g_clon = (double *)malloc(g_nxgrid*sizeof(double));
	    g_clat = (double *)malloc(g_nxgrid*sizeof(double));
	    mpp_gather_field_int   (nxgrid, i_in,       g_i_in);
	    mpp_gather_field_int   (nxgrid, j_in,       g_j_in);
	    mpp_gather_field_double(nxgrid, xgrid_area, g_area);
	    mpp_gather_field_double(nxgrid, xgrid_clon, g_clon);
	    mpp_gather_field_double(nxgrid, xgrid_clat, g_clat);
	    for(i=0; i<g_nxgrid; i++) {
	      ii = g_j_in[i]*nx_in+g_i_in[i];
	      cell_in[m].area[ii] += g_area[i];
	      cell_in[m].clon[ii] += g_clon[i];
	      cell_in[m].clat[ii] += g_clat[i];
	    }
	    free(g_i_in);
	    free(g_j_in);
	    free(g_area);
	    free(g_clon);
	    free(g_clat);
	  }
	}
	else
	  mpp_error("conserve_interp: interp_method should be CONSERVE_ORDER1 or CONSERVE_ORDER2");

	free(mask);
	if(nxgrid > 0) {
	  nxgrid_prev = interp[n].nxgrid;
	  interp[n].nxgrid += nxgrid;
	  if(nxgrid_prev == 0 ) {
	    interp[n].i_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].j_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].i_out  = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].j_out  = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].area   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	    interp[n].t_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    for(i=0; i<interp[n].nxgrid; i++) {
	      interp[n].t_in [i] = m;
	      interp[n].i_in [i] = i_in [i];
	      interp[n].j_in [i] = j_in [i];
	      interp[n].i_out[i] = i_out[i];
	      interp[n].j_out[i] = j_out[i];
	      interp[n].area[i]  = xgrid_area[i];
	    }
	    if(opcode & CONSERVE_ORDER2) {
	      interp[n].di_in   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	      interp[n].dj_in   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	      for(i=0; i<interp[n].nxgrid; i++) {
		jj = j_in [i]*nx_in+i_in [i];
		interp[n].di_in [i] = xgrid_clon[i]/xgrid_area[i];
		interp[n].dj_in [i] = xgrid_clat[i]/xgrid_area[i];
	      }
	    }
	  }
	  else {
	    tmp_i_in  = interp[n].i_in;
	    tmp_j_in  = interp[n].j_in;
	    tmp_i_out = interp[n].i_out;
	    tmp_j_out = interp[n].j_out;
	    tmp_area  = interp[n].area;
	    tmp_t_in  = interp[n].t_in;
	    interp[n].i_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].j_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].i_out  = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].j_out  = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    interp[n].area   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	    interp[n].t_in   = (int    *)malloc(interp[n].nxgrid*sizeof(int   ));
	    for(i=0; i<nxgrid_prev; i++) {
	      interp[n].t_in [i] = tmp_t_in [i];
	      interp[n].i_in [i] = tmp_i_in [i];
	      interp[n].j_in [i] = tmp_j_in [i];
	      interp[n].i_out[i] = tmp_i_out[i];
	      interp[n].j_out[i] = tmp_j_out[i];
	      interp[n].area [i] = tmp_area [i];
	    }
	    for(i=0; i<nxgrid; i++) {
	      ii = i + nxgrid_prev;
	      interp[n].t_in [ii] = m;
	      interp[n].i_in [ii] = i_in [i];
	      interp[n].j_in [ii] = j_in [i];
	      interp[n].i_out[ii] = i_out[i];
	      interp[n].j_out[ii] = j_out[i];
	      interp[n].area [ii] = xgrid_area[i];
	    }
	    if(opcode & CONSERVE_ORDER2) {
	      tmp_di_in  = interp[n].di_in;
	      tmp_dj_in  = interp[n].dj_in;
	      interp[n].di_in   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	      interp[n].dj_in   = (double *)malloc(interp[n].nxgrid*sizeof(double));
	      for(i=0; i<nxgrid_prev; i++) { 
		interp[n].di_in [i] = tmp_di_in [i];
		interp[n].dj_in [i] = tmp_dj_in [i];
	      }
	      for(i=0; i<nxgrid; i++) {
		ii = i + nxgrid_prev;
		jj = j_in [i]*nx_in+i_in [i];
		interp[n].di_in [ii] = xgrid_clon[i]/xgrid_area[i];
		interp[n].dj_in [ii] = xgrid_clat[i]/xgrid_area[i];
	      }
	      free(tmp_di_in);
	      free(tmp_dj_in);
	    }
	    free(tmp_t_in);
	    free(tmp_i_in);
	    free(tmp_j_in);
	    free(tmp_i_out);
	    free(tmp_j_out);
	    free(tmp_area);
	  }
	}  /* if(nxgrid>0) */
      }
    }
    if(opcode & CONSERVE_ORDER2) {
      /* subtrack the grid_in clon and clat to get the distance between xgrid and grid_in */
      for(n=0; n<ntiles_in; n++) {
	double *area_in;
	double x1_in[50], y1_in[50], lon_in_avg, clon, clat;
	int    j, n0, n1, n2, n3, n1_in;
	/* calcualte cell area */
     	nx_in = grid_in[n].nx;
	ny_in = grid_in[n].ny;
	area_in = (double *)malloc(nx_in*ny_in*sizeof(double));
	get_grid_area(&nx_in, &ny_in, grid_in[n].lonc, grid_in[n].latc, area_in);	
	for(j=0; j<ny_in; j++) for(i=0; i<nx_in; i++) {
	  ii = j*nx_in + i;
	  if(cell_in[n].area[ii] > 0) {
	    if( fabs(cell_in[n].area[ii]-area_in[ii])/area_in[ii] < AREA_RATIO ) {
	      cell_in[n].clon[ii] /= cell_in[n].area[ii];
	      cell_in[n].clat[ii] /= cell_in[n].area[ii];
	    }
	    else {
	      n0 = j*(nx_in+1)+i;       n1 = j*(nx_in+1)+i+1;
	      n2 = (j+1)*(nx_in+1)+i+1; n3 = (j+1)*(nx_in+1)+i;
	      x1_in[0] = grid_in[n].lonc[n0]; y1_in[0] = grid_in[n].latc[n0];
	      x1_in[1] = grid_in[n].lonc[n1]; y1_in[1] = grid_in[n].latc[n1];
	      x1_in[2] = grid_in[n].lonc[n2]; y1_in[2] = grid_in[n].latc[n2];
	      x1_in[3] = grid_in[n].lonc[n3]; y1_in[3] = grid_in[n].latc[n3];
	      n1_in = fix_lon(x1_in, y1_in, 4, M_PI);
	      lon_in_avg = avgval_double(n1_in, x1_in);
              clon = poly_ctrlon(x1_in, y1_in, n1_in, lon_in_avg);
	      clat = poly_ctrlat (x1_in, y1_in, n1_in );
	      cell_in[n].clon[ii] = clon/area_in[ii];
	      cell_in[n].clat[ii] = clat/area_in[ii];
	    }
	  } 
	}
	free(area_in);
      }
      for(n=0; n<ntiles_out; n++) {
	for(i=0; i<interp[n].nxgrid; i++) {
	  tile = interp[n].t_in[i];
	  ii   = interp[n].j_in[i] * grid_in[tile].nx + interp[n].i_in[i];
          interp[n].di_in[i] -= cell_in[tile].clon[ii];
	  interp[n].dj_in[i] -= cell_in[tile].clat[ii];
	}
      }

      /* free the memory */
      for(n=0; n<ntiles_in; n++) {
	free(cell_in[n].area);
	free(cell_in[n].clon);
	free(cell_in[n].clat);
      }
      free(cell_in);
    }
    if( opcode & WRITE) { /* write out remapping information */
      for(n=0; n<ntiles_out; n++) {
	int nxgrid;
	
	nxgrid = interp[n].nxgrid;
	mpp_sum_int(1, &nxgrid);
	if(nxgrid > 0) {
	  size_t start[4], nwrite[4];
	  int    fid, dim_string, dim_ncells, dim_two, dims[4];
	  int    id_xgrid_area, id_tile1_dist;
	  int    id_tile1_cell, id_tile2_cell, id_tile1;
	  int    *gdata_int, *ldata_int;	  
	  double *gdata_dbl;
	  
	  fid = mpp_open( interp[n].remap_file, MPP_WRITE);
	  dim_string = mpp_def_dim(fid, "string", STRING);
	  dim_ncells = mpp_def_dim(fid, "ncells", nxgrid);
	  dim_two    = mpp_def_dim(fid, "two", 2);
	  dims[0] = dim_ncells; dims[1] = dim_two;
	  id_tile1      = mpp_def_var(fid, "tile1",      NC_INT, 1, &dim_ncells, 1,
				      "standard_name", "tile_number_in_mosaic1");
	  id_tile1_cell = mpp_def_var(fid, "tile1_cell", NC_INT, 2, dims, 1,
				      "standard_name", "parent_cell_indices_in_mosaic1");
	  id_tile2_cell = mpp_def_var(fid, "tile2_cell", NC_INT, 2, dims, 1,
				      "standard_name", "parent_cell_indices_in_mosaic2");
	  id_xgrid_area = mpp_def_var(fid, "xgrid_area", NC_DOUBLE, 1, &dim_ncells, 2,
				      "standard_name", "exchange_grid_area", "units", "m2");
	  if(opcode & CONSERVE_ORDER2) id_tile1_dist = mpp_def_var(fid, "tile1_distance", NC_DOUBLE, 2, dims, 1,
								   "standard_name", "distance_from_parent1_cell_centroid");
	  mpp_end_def(fid);
	  for(i=0; i<4; i++) {
	    start[i] = 0; nwrite[i] = 1;
	  }
	  nwrite[0] = nxgrid;
	  gdata_int = (int *)malloc(nxgrid*sizeof(int));
	  if(interp[n].nxgrid>0) ldata_int = (int *)malloc(interp[n].nxgrid*sizeof(int));
	  gdata_dbl = (double *)malloc(nxgrid*sizeof(double));
	  mpp_gather_field_double(interp[n].nxgrid, interp[n].area, gdata_dbl);
	  mpp_put_var_value(fid, id_xgrid_area, gdata_dbl);
	  mpp_gather_field_int(interp[n].nxgrid, interp[n].t_in, gdata_int);
	  for(i=0; i<nxgrid; i++) gdata_int[i]++;
	  mpp_put_var_value(fid, id_tile1, gdata_int);
	  mpp_gather_field_int(interp[n].nxgrid, interp[n].i_in, gdata_int);
	  for(i=0; i<nxgrid; i++) gdata_int[i]++;
	  mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, gdata_int);
	  if(opcode & CONSERVE_ORDER2) {
	    mpp_gather_field_double(interp[n].nxgrid, interp[n].di_in, gdata_dbl);
	    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, gdata_dbl);
	  }
	  for(i=0; i<interp[n].nxgrid; i++) ldata_int[i] = interp[n].i_out[i] + grid_out[n].isc + 1; 
	  mpp_gather_field_int(interp[n].nxgrid, ldata_int, gdata_int);
	  mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, gdata_int);
	  mpp_gather_field_int(interp[n].nxgrid, interp[n].j_in, gdata_int);
	  for(i=0; i<nxgrid; i++) gdata_int[i]++;
	  start[1] = 1;
	  mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, gdata_int);
	  if(opcode & CONSERVE_ORDER2) {
	    mpp_gather_field_double(interp[n].nxgrid, interp[n].dj_in, gdata_dbl);
	    mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, gdata_dbl);
	  }
	  for(i=0; i<interp[n].nxgrid; i++) ldata_int[i] = interp[n].j_out[i] + grid_out[n].jsc + 1; 	  
	  mpp_gather_field_int(interp[n].nxgrid, ldata_int, gdata_int);
	  mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, gdata_int);
	  free(gdata_int);
	  free(gdata_dbl);
	  if(interp[n].nxgrid>0)free(ldata_int);
	  mpp_close(fid);
	}
      }
    }
    if(mpp_pe() == mpp_root_pe())printf("NOTE: done calculating index and weight for conservative interpolation\n");
  }
  /* get target grid area if needed */
  if( opcode & TARGET ) {
    for(n=0; n<ntiles_out; n++) {
      nx_out    = grid_out[n].nxc;
      ny_out    = grid_out[n].nyc; 
      grid_out[n].area = (double *)malloc(nx_out*ny_out*sizeof(double));
      get_grid_area(&nx_out,&ny_out, grid_out[n].lonc,  grid_out[n].latc, grid_out[n].area);
    }
  }
  free(i_in);
  free(j_in);
  free(i_out);
  free(j_out);
  free(xgrid_area);
  if(opcode & CONSERVE_ORDER2) {
    free(xgrid_clon);
    free(xgrid_clat);
  }
  
}; /* setup_conserve_interp */
Exemple #7
0
int main(int argc, char* argv[])
{
  char   *mosaic_file = NULL, *topog_file = NULL, *topog_field = NULL;
  char   topog_type[32] = "realistic", topog_mosaic[128] = "topog_mosaic";
  char   output_file[256];
  int    num_filter_pass = 1;
  int    x_refine = 2, y_refine = 2;
  double basin_depth = 5000, bottom_depth = 5000, min_depth = 10, scale_factor = 1;
  double gauss_amp = 0.5, gauss_scale = 0.25, slope_x = 0, slope_y = 0;
  double bowl_south = 60, bowl_north = 70, bowl_west = 0, bowl_east = 20;
  int    flat_bottom = 0, fill_first_row = 0;
  int    filter_topog = 0, round_shallow = 0, fill_shallow = 0;
  int    deepen_shallow = 0, smooth_topo_allow_deepening = 0;
  int    errflg = (argc == 1);
  int    option_index, i, c;

  
  /*
   * process command line
   */

  static struct option long_options[] = {
    {"mosaic",                      required_argument, NULL, 'a'},
    {"topog_type",                  required_argument, NULL, 'b'},
    {"x_refine",                    required_argument, NULL, 'X'},
    {"y_refine",                    required_argument, NULL, 'Y'},
    {"basin_depth",                 required_argument, NULL, 'c'},
    {"topog_file",                  required_argument, NULL, 'd'},
    {"topog_field",                 required_argument, NULL, 'e'},
    {"bottom_depth",                required_argument, NULL, 'f'},
    {"min_depth",                   required_argument, NULL, 'g'},
    {"scale_factor",                required_argument, NULL, 'i'},
    {"num_filter_pass",             required_argument, NULL, 'j'},
    {"gauss_amp",                   required_argument, NULL, 'k'},
    {"gauss_scale",                 required_argument, NULL, 'l'},
    {"slope_x",                     required_argument, NULL, 'm'},    
    {"slope_y",                     required_argument, NULL, 'n'},
    {"bowl_south",                  required_argument, NULL, 'p'},
    {"bowl_north",                  required_argument, NULL, 'q'},
    {"bowl_west",                   required_argument, NULL, 'r'},
    {"bowl_east",                   required_argument, NULL, 's'},
    {"fill_first_row",              no_argument,       NULL, 't'},
    {"filter_topog",                no_argument,       NULL, 'u'},    
    {"round_shallow",               no_argument,       NULL, 'v'},
    {"fill_shallow",                no_argument,       NULL, 'w'},
    {"deepen_shallow",              no_argument,       NULL, 'x'},
    {"smooth_topo_allow_deepening", no_argument,       NULL, 'y'},
    {"topog_mosaic",                required_argument, NULL, 'o'},
    {"help",                        no_argument,       NULL, 'h'},
    {0, 0, 0, 0},
  };

  /* start parallel */

  mpp_init(&argc, &argv);

  mpp_domain_init();  
   
  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1)
    switch (c) {
    case 'a':
      mosaic_file = optarg;
      break;      
    case 'b':
      strcpy(topog_type, optarg);
      break;
    case 'X':
      x_refine = atoi(optarg);
      break;
    case 'Y':
      y_refine = atoi(optarg);
      break;      
    case 'c':
      basin_depth = atof(optarg);
      break;
    case 'd':
      topog_file = optarg;
      break;
    case 'e':
      topog_field = optarg;
      break;
    case 'f':
      bottom_depth = atof(optarg);
      break; 
    case 'g':
      min_depth = atof(optarg);
      break;
    case 'i':
      scale_factor = atof(optarg);
      break;
    case 'j':
      num_filter_pass = atoi(optarg);
      break; 
    case 'k':
      gauss_amp = atof(optarg);
      break;
    case 'l':
      gauss_scale = atof(optarg);
      break;
    case 'm':
      slope_x = atof(optarg);
      break;
    case 'n':
      slope_y = atof(optarg);
      break;
    case 'p':
      bowl_south = atof(optarg);
      break;
    case 'q':
      bowl_north = atof(optarg);
      break;
    case 'r':
      bowl_west  = atof(optarg);
      break;
    case 's':
      bowl_east  = atof(optarg);
      break;
    case 't':
      fill_first_row = 1;
      break;
    case 'u':
      filter_topog = 1;
      break;
    case 'v':
      round_shallow = 1;
      break;
    case 'w':
      fill_shallow = 1;
      break;
    case 'x':
      deepen_shallow = 1;
      break;
    case 'y':
      smooth_topo_allow_deepening = 1;
      break;
    case 'o':
      strcpy(topog_mosaic,optarg);
      break; 
    case '?':
      errflg++;
      break;
    }

  if (errflg || !mosaic_file ) {
    char **u = usage;
    while (*u) { fprintf(stderr, "%s\n", *u); u++; }
    exit(2);
  }


  /* Write out arguments value  */
  if(mpp_pe() == mpp_root_pe()) printf("NOTE from make_topog ==> the topog_type is: %s\n",topog_type);
  if(x_refine != 2 || y_refine != 2 ) mpp_error("Error from make_topog: x_refine and y_refine should be 2, contact developer");
  if(mpp_pe() == mpp_root_pe()) printf("NOTE from make_topog ==> x_refine is %d, y_refine is %d\n",
				       x_refine, y_refine);

  if (strcmp(topog_type,"rectangular_basin") == 0) {
    if(mpp_pe() == mpp_root_pe()) printf("NOTE from make_topog ==> the basin depth is %f\n",basin_depth);
  }
  else if (strcmp(topog_type,"gaussian") == 0) {
    if(mpp_pe() == mpp_root_pe()){
      printf("NOTE from make_topog ==> bottom_depth is: %f\n", bottom_depth );
      printf("NOTE from make_topog ==> min_depth is: %f\n", min_depth );
      printf("NOTE from make_topog ==> gauss_amp is: %f\n", gauss_amp );
      printf("NOTE from make_topog ==> gauss_scale is: %f\n", gauss_scale );
      printf("NOTE from make_topog ==> slope_x is: %f\n", slope_x );
      printf("NOTE from make_topog ==> slope_y is: %f\n", slope_y );      
    }
  }
  else if(strcmp(topog_type,"bowl") == 0) {
    if(mpp_pe() == mpp_root_pe()){
      printf("NOTE from make_topog ==> bottom_depth is: %f\n",bottom_depth);
      printf("NOTE from make_topog ==> min_depth is: %f\n",min_depth);
      printf("NOTE from make_topog ==> bowl_south is: %f\n",bowl_south);
      printf("NOTE from make_topog ==> bowl_north is: %f\n",bowl_north);
      printf("NOTE from make_topog ==> bowl_west is: %f\n",bowl_west);
      printf("NOTE from make_topog ==> bowl_east is: %f\n",bowl_east);
    }
  }
  else if(strcmp(topog_type,"idealized") == 0) {
    if(mpp_pe() == mpp_root_pe()){
      printf("NOTE from make_topog ==> bottom_depth is: %f\n",bottom_depth);
      printf("NOTE from make_topog ==> min_depth is: %f\n",min_depth);
    }
  }
  else if(strcmp(topog_type,"realistic") == 0) {
    if(!topog_file || !topog_field)
      mpp_error("Error from make_topog: when topog_type is realistic, topog_file and topog_field must be specified.");
    if(mpp_pe() == mpp_root_pe()){
      printf("NOTE from make_topog ==> bottom_depth is: %f\n",bottom_depth);
      printf("NOTE from make_topog ==> min_depth is: %f\n",min_depth);
      printf("NOTE from make_topog ==> topog_file is: %s\n", topog_file);
      printf("NOTE from make_topog ==> topog_field is: %s\n", topog_field);
      printf("NOTE from make_topog ==> scale_factor is: %f\n", scale_factor);
      printf("NOTE from make_topog ==> num_filter_pass is: %d\n", num_filter_pass);
      if(fill_first_row) printf("NOTE from make_topog ==>make first row of ocean model all land points.\n");
      if(filter_topog) printf("NOTE from make_topog ==>will apply filter to topography.\n");
      if(round_shallow) printf("NOTE from make_topog ==>Make cells land if depth is less than 1/2 "
			       "mimumim depth, otherwise make ocean.\n");
      if(fill_shallow) printf("NOTE from make_topog ==>Make cells less than minimum depth land.\n");
      if(deepen_shallow) printf("NOTE from make_topog ==>Make cells less than minimum depth equal to minimum depth.\n");
      if(smooth_topo_allow_deepening) printf("NOTE from make_topog ==>allow filter to deepen cells.\n");
    }
  }
  else {
    mpp_error("make_topog: topog_type should be rectangular_basin, gaussian, bowl, idealized or realistic");
  }
  
  if(mpp_pe() == mpp_root_pe()) {
    printf("**************************************************\n");
    printf("Begin to generate topography \n");
  }

  {
    int m_fid, g_fid, vid;
    int ntiles, fid, dim_ntiles, n, dims[2];
    size_t start[4], nread[4], nwrite[4];
    int *nx, *ny, *nxp, *nyp;
    int *id_depth;
    double *depth, *x, *y;
    int  *t_fid;
    int  dim_nchild, dim_string, id_mosaic, id_childfile;
    char **tile_files, **topog_files;
    char history[512];
    char gridfile[256], griddir[256];
    
    /* history will be write out as global attribute
       in output file to specify the command line arguments
    */

    strcpy(history,argv[0]);

    for(i=1;i<argc;i++) {
      strcat(history, " ");
      strcat(history, argv[i]);
    }

    /* grid should be located in the same directory of mosaic file */
    get_file_path(mosaic_file, griddir);
    
    /* get mosaic dimension */
    m_fid = mpp_open(mosaic_file, MPP_READ);
    ntiles = mpp_get_dimlen( m_fid, "ntiles");
    tile_files  = (char **)malloc(ntiles*sizeof(char *));
    topog_files = (char **)malloc(ntiles*sizeof(char *));
    t_fid       = (int *)  malloc(ntiles*sizeof(int ));
    id_depth = (int *)malloc(ntiles*sizeof(int));
    /* loop through each tile to get tile information and set up meta data for output file */
    sprintf(output_file, "%s.nc", topog_mosaic);
    fid = mpp_open(output_file, MPP_WRITE);
    mpp_def_global_att(fid, GRID_VERSION_NAME, grid_version);
    mpp_def_global_att(fid, CODE_VERSION_NAME, tagname);
    mpp_def_global_att(fid, HISTORY_NAME, history);
    dim_nchild = mpp_def_dim(fid, NTILES_NAME, ntiles);
    dim_string = mpp_def_dim(fid, STRING_NAME, STRING);
    id_mosaic = mpp_def_var(fid, MOSAIC_FILES_NAME, MPP_CHAR, 1, &dim_string, 1, "standard_name", "grid_mosaic_files");
    dims[0] = dim_nchild; dims[1] = dim_string;
    id_childfile = mpp_def_var(fid, TILE_FILES_NAME, MPP_CHAR, 2, dims, 0);
    mpp_end_def(fid);
    
    nx = (int *)malloc(ntiles*sizeof(int));
    ny = (int *)malloc(ntiles*sizeof(int));
    nxp = (int *)malloc(ntiles*sizeof(int));
    nyp = (int *)malloc(ntiles*sizeof(int));
    
    for( n = 0; n < ntiles; n++ ) {
      char tile_name[128];
      tile_files[n] = (char *)malloc(STRING*sizeof(double));
      topog_files[n] = (char *)malloc(STRING*sizeof(double));
      start[0] = n;
      start[1] = 0;
      nread[0] = 1;
      nread[1] = STRING;
      vid = mpp_get_varid(m_fid, TILE_FILES_NAME);
      mpp_get_var_value_block(m_fid, vid, start, nread, gridfile);
      sprintf(tile_files[n], "%s/%s", griddir, gridfile);
      
      g_fid = mpp_open(tile_files[n], MPP_READ);
      vid = mpp_get_varid(g_fid, "tile");
      mpp_get_var_value(g_fid, vid, tile_name);
      sprintf(topog_files[n],"%s.%s.nc", topog_mosaic, tile_name);
      nx[n] = mpp_get_dimlen(g_fid, "nx");
      ny[n] = mpp_get_dimlen(g_fid, "ny");
      if( nx[n]%x_refine != 0 ) mpp_error("make_topog: supergrid x-size can not be divided by x_refine");
      if( ny[n]%y_refine != 0 ) mpp_error("make_topog: supergrid y-size can not be divided by y_refine");
      nx[n] /= x_refine;
      ny[n] /= y_refine;
      nxp[n] = nx[n] + 1;
      nyp[n] = ny[n] + 1;

      t_fid[n] = mpp_open(topog_files[n], MPP_WRITE);
      mpp_def_global_att(t_fid[n], GRID_VERSION_NAME, grid_version);
      mpp_def_global_att(t_fid[n], CODE_VERSION_NAME, tagname);
      mpp_def_global_att(t_fid[n], HISTORY_NAME, history);      
      dims[1] = mpp_def_dim(t_fid[n], NX_NAME, nx[n]); 
      dims[0] = mpp_def_dim(t_fid[n], NY_NAME, ny[n]);
      id_depth[n] = mpp_def_var(t_fid[n], DEPTH_NAME, NC_DOUBLE, 2, dims,  2, "standard_name",
				"topographic depth at T-cell centers", "units", "meters");
      mpp_close(g_fid);
      mpp_end_def(t_fid[n]);
    }
    mpp_close(m_fid);

    /* Generate topography and write out to the output_file */
    for(n=0; n<ntiles; n++) {
      int layout[2], isc, iec, jsc, jec, nxc, nyc, ni, i, j;
      double *gdata, *tmp;
      domain2D domain;
      
      /* define the domain, each tile will be run on all the processors. */
      mpp_define_layout( nx[n], ny[n], mpp_npes(), layout);
      mpp_define_domain2d( nx[n], ny[n], layout, 0, 0, &domain);
      mpp_get_compute_domain2d( domain, &isc, &iec, &jsc, &jec);
      nxc = iec - isc + 1;
      nyc = jec - jsc + 1;
      
      depth = (double *)malloc(nxc*nyc*sizeof(double));
      x     = (double *)malloc((nxc+1)*(nyc+1)*sizeof(double));
      y     = (double *)malloc((nxc+1)*(nyc+1)*sizeof(double));
      tmp   = (double *)malloc((nxc*x_refine+1)*(nyc*y_refine+1)*sizeof(double));
      start[0] = jsc*y_refine; start[1] = isc*x_refine;
      nread[0] = nyc*y_refine+1; nread[1] = nxc*x_refine+1;
      ni       = nxc*x_refine+1;
      g_fid = mpp_open(tile_files[n], MPP_READ);
      vid = mpp_get_varid(g_fid, "x");
      mpp_get_var_value_block(g_fid, vid, start, nread, tmp);
      for(j = 0; j < nyc+1; j++) for(i = 0; i < nxc+1; i++)
	x[j*(nxc+1)+i] = tmp[(j*y_refine)*ni+i*x_refine];
      vid = mpp_get_varid(g_fid, "y");
      mpp_get_var_value_block( g_fid, vid, start, nread, tmp);
      mpp_close(g_fid);
      for(j = 0; j < nyc+1; j++) for(i = 0; i < nxc+1; i++)
	y[j*(nxc+1)+i] = tmp[(j*y_refine)*ni+i*x_refine];
      if (strcmp(topog_type,"rectangular_basin") == 0)
	create_rectangular_topog(nx[n], ny[n], basin_depth, depth);
      else if (strcmp(topog_type,"gaussian") == 0)
	create_gaussian_topog(nx[n], ny[n], x, y, bottom_depth, min_depth,
			      gauss_amp, gauss_scale, slope_x, slope_y, depth);
      else if (strcmp(topog_type,"bowl") == 0)
	create_bowl_topog(nx[n], ny[n], x, y, bottom_depth, min_depth, bowl_east,
			  bowl_south, bowl_west, bowl_north, depth);
      else if (strcmp(topog_type,"idealized") == 0)
	create_idealized_topog( nx[n], ny[n], x, y, bottom_depth, min_depth, depth);
      else if (strcmp(topog_type,"realistic") == 0)
	create_realistic_topog(nxc, nyc, x, y, topog_file, topog_field, scale_factor,
			       fill_first_row, filter_topog, num_filter_pass,
			       smooth_topo_allow_deepening, round_shallow, fill_shallow,
			       deepen_shallow, min_depth, depth );
      gdata = (double *)malloc(nx[n]*ny[n]*sizeof(double));
      mpp_global_field_double(domain, nxc, nyc, depth, gdata);
      mpp_put_var_value(t_fid[n], id_depth[n], gdata);
      free(x);
      free(y);
      free(tmp);
      free(depth);
      free(gdata);
      mpp_delete_domain2d(&domain);
      mpp_close(t_fid[n]);
    }

    for(i=0; i<4; i++) {
      start[i] = 0; nwrite[i] = 1;
    }
    nwrite[0] = strlen(mosaic_file);
    mpp_put_var_value_block(fid, id_mosaic, start, nwrite, mosaic_file);
    nwrite[0] = 1;
    for(n=0; n<ntiles; n++) {
      start[0]=n;
      nwrite[1]=strlen(topog_files[n]);
      mpp_put_var_value_block(fid, id_childfile, start, nwrite, topog_files[n]);
    }
    mpp_close(fid);
  
    /*release memory */
    free(id_depth);
    for(n=0; n<ntiles; n++) {
      free(tile_files[n]);
      free(topog_files[n]);
    }
    free(tile_files);
    free(topog_files);
    free(t_fid);
    free(nx);
    free(ny);
    free(nxp);
    free(nyp);
  }
    
  if(mpp_pe() == mpp_root_pe() ) printf("Successfully generate %s\n",output_file);

  mpp_end();

  return 0;
}; //main
/***********************************************************************
  void create_grid_from_file( char *file, int *nlon, int *nlat, double *x, double *y, double *dx,
                              double *dy, double *area, double *angle_dx )
   the grid location is defined through ascii file. calculate cell length,
   cell area and rotation angle  
************************************************************************/
void create_grid_from_file( char *file, int *nlon, int *nlat, double *x, double *y, double *dx, double *dy,
           		    double *area, double *angle_dx )
{
  double *xb, *yb, *xt, *yt, *xc, *yc;
  double p1[4], p2[4];
  int nx, ny, nxp, nyp, ni, nj, i, j, n;
  FILE *pFile;
  char mesg[256], txt[128];
  
  /************************************************************
     identify the grid_file is ascii file or netcdf file,
     if the file name contains ".nc", it is a netcdf file,
     otherwise it is ascii file.
  *********************************************************/
  nx  = *nlon;
  ny  = *nlat;
  nxp = nx + 1;
  nyp = ny + 1;
  if(strstr(file, ".nc") ) {
    int fid, vid;

    ni  = *nlon/2;
    nj  = *nlat/2;
    xc = (double *)malloc((ni+1)*(nj+1)*sizeof(double));
    yc = (double *)malloc((ni+1)*(nj+1)*sizeof(double));
    xt = (double *)malloc( ni   * nj   *sizeof(double));
    yt = (double *)malloc( ni   * nj   *sizeof(double));
    fid = mpp_open(file, MPP_READ);
    vid = mpp_get_varid(fid, "grid_lon");
    mpp_get_var_value(fid, vid, xc);
    vid = mpp_get_varid(fid, "grid_lat");
    mpp_get_var_value(fid, vid, yc);
    vid = mpp_get_varid(fid, "grid_lont");
    mpp_get_var_value(fid, vid, xt);
    vid = mpp_get_varid(fid, "grid_latt");
    mpp_get_var_value(fid, vid, yt);
    mpp_close(fid);
    for(j=0; j<nj+1; j++) for(i=0; i<ni+1; i++) {
      x[j*2*nxp+i*2] = xc[j*(ni+1)+i];
      y[j*2*nxp+i*2] = yc[j*(ni+1)+i];
    }
    for(j=0; j<nj; j++) for(i=0; i<ni; i++) {
      x[(j*2+1)*nxp+i*2+1] = xt[j*ni+i];
      y[(j*2+1)*nxp+i*2+1] = yt[j*ni+i];
    }
    for(j=0; j<nj+1; j++) for(i=0; i<ni; i++) {
      x[j*2*nxp+i*2+1] = (xc[j*(ni+1)+i]+xc[j*(ni+1)+i+1])*0.5;
      y[j*2*nxp+i*2+1] = (yc[j*(ni+1)+i]+yc[j*(ni+1)+i+1])*0.5;
    }    
    for(j=0; j<nj; j++) for(i=0; i<ni+1; i++) {
      x[(j*2+1)*nxp+i*2] = (xc[j*(ni+1)+i]+xc[(j+1)*(ni+1)+i])*0.5;
      y[(j*2+1)*nxp+i*2] = (yc[j*(ni+1)+i]+yc[(j+1)*(ni+1)+i])*0.5;
    }

    for(j=0; j<nyp; j++) for(i=0; i<nx; i++) {
      p1[0] = x[j*nxp+i]; p2[0] = x[j*nxp+i+1];
      p1[1] = y[j*nxp+i]; p2[1] = y[j*nxp+i+1];
      dx[j*nx+i] = great_circle_distance(p1, p2);
    }
    for(j=0; j<ny; j++) for(i=0; i<nxp; i++) {
      p1[0] = x[j*nxp+i]; p2[0] = x[(j+1)*nxp+i];
      p1[1] = y[j*nxp+i]; p2[1] = y[(j+1)*nxp+i];
      dy[j*nxp+i] = great_circle_distance(p1, p2);
    }    
    for(j=0; j<ny; j++) for(i=0; i<nx; i++) {
      p1[0] = x[j*nxp+i]; p1[1] = x[j*nxp+i+1]; p1[2] = x[(j+1)*nxp+i+1]; p1[3] = x[(j+1)*nxp+i];
      p2[0] = y[j*nxp+i]; p2[1] = y[j*nxp+i+1]; p2[2] = y[(j+1)*nxp+i+1]; p2[3] = y[(j+1)*nxp+i];
      area[j*nx+i] = poly_area(p1, p2, 4);
    }
    /* currently set angle to 0 */
    for(j=0; j<nyp; j++) for(i=0; i<nxp; i++) angle_dx[j*nxp+i] = 0;    
    free(xt);
    free(yt);
    free(xc);
    free(yc);
  }
  else {
    pFile = fopen (file,"r");
    if(!pFile) {
      strcpy(mesg, "RegularSphericalGrid: Can not open ascii file ");
      strcat(mesg,file);
      mpp_error(mesg);
    }

    fscanf(pFile, "%s%*[^\n]",txt); /* header line (ignored) */
    xb = (double *) malloc(nxp*sizeof(double));
    yb = (double *) malloc(nyp*sizeof(double));
    for(i=0;i<nxp;i++) 
      fscanf(pFile, "%lg", xb+i); /* longitude */ 
    fscanf(pFile, "%s%*[^\n]",txt); /* header line (ignored) */   
    for(j=0;j<nyp;j++) fscanf(pFile, "%lg", yb+j); /* latitude */
    
    fclose(pFile);
    n=0;
    for(j=0; j<nyp; j++) {
      for(i=0; i<nxp; i++) {
	x[n]       = xb[i];
	y[n]       = yb[j];
	angle_dx[n++] = 0;   
      }
    }
    /* zonal length */
    n = 0;
    for(j=0; j<nyp; j++) {
      for(i=0; i<nx; i++ ) {
	dx[n++] = spherical_dist(x[j*nxp+i], y[j*nxp+i], x[j*nxp+i+1], y[j*nxp+i+1] );
      }
    }

    /* meridinal length */
    n = 0;
    for(j=0; j<ny; j++) {
      for(i=0; i<nxp; i++ ) {
	dy[n++] = spherical_dist(x[j*nxp+i], y[j*nxp+i], x[(j+1)*nxp+i], y[(j+1)*nxp+i] );
      }
    }

    /* cell area */
    n = 0;
    for(j=0; j<ny; j++) {
      for(i=0; i<nx; i++ ) {
	area[n++] = box_area(x[j*nxp+i]*D2R, y[j*nxp+i]*D2R, x[(j+1)*nxp+i+1]*D2R, y[(j+1)*nxp+i+1]*D2R );
      }
    }

    free(xb);
    free(yb);
  }
}; /* create_grid_from_file */