Beispiel #1
0
/* close the file */
void mpp_close(int fid)
{
  int status;
  char errmsg[512];

  if(fid == -1 && mpp_pe() != mpp_root_pe() ) return;
  
  if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_close): invalid id number, id should be "
				    "a nonnegative integer that less than nfiles");
  
  status = nc_close(files[fid].ncid);
  if(status != NC_NOERR) {
    sprintf( errmsg, "mpp_io(mpp_close): error in closing files %s ", files[fid].name);
    netcdf_error(errmsg, status);
  }
  files[fid].ncid = 0;
  files[fid].status = 0;
  
}
Beispiel #2
0
/**********************************************************************
  void mpp_copy_var_att(fid_in, fid_out)
  copy all the field attribute from infile to outfile
**********************************************************************/
void mpp_copy_var_att(int fid_in, int vid_in, int fid_out, int vid_out)
{
  int natt, status, i, ncid_in, ncid_out, fldid_in, fldid_out;
  char name[256];
  char errmsg[512];

  if( mpp_pe() != mpp_root_pe() ) return;
  
  if(fid_in<0 || fid_in >=nfiles) mpp_error("mpp_io(mpp_copy_var_att): invalid fid_in number, fid should be "
				      "a nonnegative integer that less than nfiles");
  if(fid_out<0 || fid_out >=nfiles) mpp_error("mpp_io(mpp_copy_var_att): invalid fid_out number, fid should be "
				      "a nonnegative integer that less than nfiles");
        
  ncid_in   = files[fid_in].ncid;
  ncid_out  = files[fid_out].ncid;  
  fldid_in  = files[fid_in].var[vid_in].fldid;
  fldid_out = files[fid_out].var[vid_out].fldid;
  
  status = nc_inq_varnatts(ncid_in, fldid_in, &natt);
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_copy_var_att): Error in inquiring natts of var %s of file %s",
	    files[fid_in].var[vid_in].name, files[fid_in].name );
    netcdf_error(errmsg, status);
  }
  
  for(i=0; i<natt; i++) {
    status = nc_inq_attname(ncid_in, fldid_in, i, name);
    if(status != NC_NOERR) {
      sprintf(errmsg, "mpp_io(mpp_copy_var_att): Error in inquiring %d attname of var %s of file %s", i, 
	      files[fid_in].var[vid_in].name, files[fid_in].name );
      netcdf_error(errmsg, status);
    }
    status = nc_copy_att(ncid_in, fldid_in, name, ncid_out, fldid_out);
    if(status != NC_NOERR) {
      sprintf(errmsg, "mpp_io(mpp_copy_var_att): Error in copying att %s of var %s of file %s", name,  
	      files[fid_in].var[vid_in].name, files[fid_in].name );
      netcdf_error(errmsg, status);
    }
  }

}; /* mpp_copy_field_att */
Beispiel #3
0
/********************************************************************
 int mpp_def_var(nt fid, const char* name, int type, int ndim, int *dims, int natts ... )
 define metadata of field.
********************************************************************/
int mpp_def_var(int fid, const char* name, nc_type type, int ndim, const int *dims, int natts, ...) {
  int fldid, status, i, vid, ncid;
  va_list ap;
  char errmsg[512];
  
  if( mpp_pe() != mpp_root_pe() ) return 0;
  if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_def_var): invalid fid number, fid should be "
				      "a nonnegative integer that less than nfiles");

  ncid = files[fid].ncid;
  status = nc_def_var(ncid, name, type, ndim, dims, &fldid);
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_def_var): Error in defining var %s of file %s",
	    name, files[fid].name );
    netcdf_error(errmsg, status);
  }
  vid = files[fid].nvar;
  files[fid].nvar++;
  if(files[fid].nvar > MAXVAR ) mpp_error("mpp_io(mpp_def_var): nvar is larger than MAXVAR, increase MAXVAR");  
  files[fid].var[vid].fldid = fldid;
  files[fid].var[vid].type = type;
  strcpy(files[fid].var[vid].name, name);
  
  va_start(ap, natts);
  for( i=0; i<natts; i++) {
    char* attname = va_arg(ap, char*);
    char* attval = va_arg(ap, char*);
    if( attname == NULL || attval == NULL) {
      mpp_error("mpp_io: attribute name and attribute value not defined suitably, check the arguments list.");
    }
    status = nc_put_att_text(ncid,fldid,attname,strlen(attval),attval);
    if(status != NC_NOERR ) {
      sprintf(errmsg, "mpp_io(mpp_def_var): Error in put attribute %s of var %s of file %s",
	      attname, name, files[fid].name );
      netcdf_error(errmsg, status);
    }
  }
  va_end(ap);
  return vid;
} /* mpp_define_var */
Beispiel #4
0
/*********************************************************************
  void mpp_put_var_value_block(int fid, int vid, const size_t *start, const size_t *nread, void *data)
  read part of var data, the part is defined by start and nread.
*********************************************************************/
void mpp_put_var_value_block(int fid, int vid, const size_t *start, const size_t *nwrite, const void *data)
{
  int status;
  char errmsg[512];

  if( mpp_pe() != mpp_root_pe() ) return;
  
  if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_put_var_value_block): invalid fid number, fid should be "
				    "a nonnegative integer that less than nfiles");
  if(vid<0 || vid >=files[fid].nvar) mpp_error("mpp_io(mpp_put_var_value_block): invalid vid number, vid should be "
				    "a nonnegative integer that less than nvar");

  switch(files[fid].var[vid].type) {
  case NC_DOUBLE:case NC_FLOAT:
    status = nc_put_vara_double(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;
  case NC_INT:
    status = nc_put_vara_int(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;
  case NC_SHORT:
    status = nc_put_vara_short(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;    
  case NC_CHAR:
    status = nc_put_vara_text(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;
  default:
    sprintf(errmsg, "mpp_io(mpp_put_var_value_block): field %s in file %s has an invalid type, "
	    "the type should be NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT or NC_CHAR",
	    files[fid].var[vid].name, files[fid].name );
    mpp_error(errmsg);
  }    
  
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_put_var_value_block): Error in putting value of variable %s from file %s",
	    files[fid].var[vid].name, files[fid].name );
    netcdf_error(errmsg, status);
  }
  
}; /* mpp_put_var_value_block */
Beispiel #5
0
int main(int argc, char* argv[])
{
  unsigned int opcode = 0;
  char    *mosaic_in=NULL;            /* input mosaic file name */
  char    *mosaic_out=NULL;           /* input mosaic file name */
  char    *dir_in=NULL;               /* input file location */
  char    *dir_out=NULL;              /* output file location */
  int     ntiles_in = 0;              /* number of tiles in input mosaic */
  int     ntiles_out = 0;             /* number of tiles in output mosaic */
  int     nfiles     = 0;              /* number of input file */
  int     nfiles_out = 0;             /* number of output file */
  char    input_file [NFILE][STRING];
  char    output_file[NFILE][STRING];
  char    scalar_name[NVAR] [STRING];
  char    u_name     [NVAR] [STRING];
  char    v_name     [NVAR] [STRING];
  char    *test_case = NULL;
  double  test_param = 1;
  int     check_conserve = 0; /* 0 means no check */
  double  lonbegin = 0, lonend = 360;
  double  latbegin = -90, latend = 90;			  
  int     nlon = 0, nlat = 0;
  int     kbegin = 0, kend = -1; 
  int     lbegin = 0, lend = -1;
  char    *remap_file = NULL;
  char    interp_method[STRING] = "conserve_order1";
  int     y_at_center = 0;
  int     grid_type = AGRID;
  int     nscalar=0, nvector=0, nvector2=0;
  int     option_index, c, i, n, m, l;
  char    entry[MAXSTRING];  /* should be long enough */
  char    txt[STRING];
  char    history[MAXATT];
  int     fill_missing = 0;
  unsigned int  finer_step = 0;

  Grid_config   *grid_in    = NULL;   /* store input grid  */
  Grid_config   *grid_out   = NULL;   /* store output grid */
  Field_config  *scalar_in  = NULL;   /* store input scalar data */
  Field_config  *scalar_out = NULL;   /* store output scalar data */
  Field_config  *u_in       = NULL;   /* store input vector u-component */
  Field_config  *v_in       = NULL;   /* store input vector v-component */
  Field_config  *u_out      = NULL;   /* store input vector u-component */
  Field_config  *v_out      = NULL;   /* store input vector v-component */
  File_config   *file_in    = NULL;   /* store input file information */
  File_config   *file_out   = NULL;   /* store output file information */
  File_config   *file2_in   = NULL;   /* store input file information */
  File_config   *file2_out  = NULL;   /* store output file information */
  Bound_config  *bound_T    = NULL;   /* store halo update information for T-cell*/
  Interp_config *interp     = NULL;   /* store remapping information */
  int save_weight_only      = 0;
  
  int errflg = (argc == 1);
  int fid;
  
  static struct option long_options[] = {
    {"input_mosaic",     required_argument, NULL, 'a'},
    {"output_mosaic",    required_argument, NULL, 'b'},
    {"input_dir",        required_argument, NULL, 'c'},
    {"output_dir",       required_argument, NULL, 'd'},
    {"input_file",       required_argument, NULL, 'e'},
    {"output_file",      required_argument, NULL, 'f'},
    {"remap_file",       required_argument, NULL, 'g'},
    {"test_case",        required_argument, NULL, 'i'},
    {"interp_method",    required_argument, NULL, 'j'},
    {"test_parameter",   required_argument, NULL, 'k'},
    {"symmetry",         no_argument,       NULL, 'l'},
    {"grid_type",        required_argument, NULL, 'm'},
    {"target_grid",      no_argument,       NULL, 'n'},
    {"finer_step",       required_argument, NULL, 'o'},
    {"fill_missing",     no_argument,       NULL, 'p'},
    {"nlon",             required_argument, NULL, 'q'},
    {"nlat",             required_argument, NULL, 'r'},
    {"scalar_field",     required_argument, NULL, 's'},
    {"check_conserve",   no_argument,       NULL, 't'},
    {"u_field",          required_argument, NULL, 'u'},
    {"v_field",          required_argument, NULL, 'v'},
    {"center_y",         no_argument,       NULL, 'y'},
    {"lonBegin",         required_argument, NULL, 'A'},
    {"lonEnd",           required_argument, NULL, 'B'},
    {"latBegin",         required_argument, NULL, 'C'},
    {"latEnd",           required_argument, NULL, 'D'},
    {"KlevelBegin",      required_argument, NULL, 'E'},
    {"KlevelEnd",        required_argument, NULL, 'F'},
    {"LstepBegin",       required_argument, NULL, 'G'},
    {"LstepEnd",         required_argument, NULL, 'H'},
    {"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_in  = optarg;
      break;
    case 'b':
      mosaic_out = optarg;
      break;
    case 'c':
      dir_in = optarg;
      break;
    case 'd':
      dir_out = optarg;
      break;
    case 'e':
      if(strlen(optarg) >= MAXSTRING) mpp_error("fregrid: the entry is not long for option -e");
      strcpy(entry, optarg);
      tokenize(entry, ",", STRING, NFILE, input_file, &nfiles);
      break;
    case 'f':
      if(strlen(optarg) >= MAXSTRING)  mpp_error("fregrid: the entry is not long for option -f");      
      strcpy(entry, optarg);
      tokenize(entry, ",", STRING, NFILE, output_file, &nfiles_out);
      break;
    case 'g':
      remap_file = optarg;
      break;
    case 's':
      if(strlen(optarg) >= MAXSTRING) mpp_error("fregrid: the entry is not long for option -s");      
      strcpy(entry, optarg);
      tokenize(entry, ",", STRING, NVAR, scalar_name, &nscalar);
      break;
    case 'u':
      if(strlen(optarg) >= MAXSTRING) mpp_error("fregrid: the entry is not long for option -u");      
      strcpy(entry, optarg);
      tokenize(entry, ",", STRING, NVAR, u_name, &nvector);
      break;        
    case 'v':
      if(strlen(optarg) >= MAXSTRING) mpp_error("fregrid: the entry is not long for option -v");      
      strcpy(entry, optarg);
      tokenize(entry, ",", STRING, NVAR, v_name, &nvector2);
      break;      
    case 'j':
      strcpy(interp_method, optarg);
      break;
    case 'i':
      test_case = optarg;
      break;
    case 'k':
      test_param = atof(optarg);
      break;      
    case 'l':
      opcode |= SYMMETRY;
      break;
    case 'm':
      if(strcmp(optarg, "AGRID") == 0)
	grid_type = AGRID;
      else if(strcmp(optarg, "BGRID") == 0)
	grid_type = BGRID;
      else
	mpp_error("fregrid: only AGRID and BGRID vector regridding are implmented, contact developer");
      break;
    case 'n':
      opcode |= TARGET;
      break;
    case 'o':
      finer_step = atoi(optarg);
      break;
    case 'p':
      fill_missing = 1;
      break;
    case 'q':
      nlon = atoi(optarg);
      break;
    case 'r':
      nlat = atoi(optarg);
      break;
    case 't':
      check_conserve = 1;
      break;
    case 'y':
      y_at_center = 1;
      break;
    case 'A':
      lonbegin = atof(optarg);
      break;
    case 'B':
      lonend = atof(optarg);
      break;
    case 'C':
      latbegin = atof(optarg);
      break;
    case 'D':
      latend = atof(optarg);
      break;
    case 'E':
      kbegin = atoi(optarg);
      break;
    case 'F':
      kend = atoi(optarg);
      break;
    case 'G':
      lbegin = atoi(optarg);
      break;
    case 'H':
      lend = atoi(optarg);
      break;
    case '?':
      errflg++;
      break;
    }
  }

  if (errflg) {
    char **u = usage;
    while (*u) { fprintf(stderr, "%s\n", *u); u++; }
    exit(2);
  }      
  /* check the arguments */
  if( !mosaic_in  ) mpp_error("fregrid: input_mosaic is not specified");
  if( !mosaic_out ) {
    if(nlon == 0 || nlat ==0 ) mpp_error("fregrid: when output_mosaic is not specified, nlon and nlat should be specified");
    if(lonend <= lonbegin) mpp_error("fregrid: when output_mosaic is not specified, lonEnd should be larger than lonBegin");
    if(latend <= latbegin) mpp_error("fregrid: when output_mosaic is not specified, latEnd should be larger than latBegin");
  }
  else {
    if(nlon !=0 || nlat != 0) mpp_error("fregrid: when output_mosaic is specified, nlon and nlat should not be specified");
  }
  
  if( nfiles == 0) {
    if(nvector > 0 || nscalar > 0 || nvector2 > 0)
      mpp_error("fregrid: when --input_file is not specified, --scalar_field, --u_field and --v_field should also not be specified");
    if(!remap_file) mpp_error("fregrid: when --input_file is not specified, remap_file must be specified to save weight information");
    save_weight_only = 1;
    if(mpp_pe()==mpp_root_pe())printf("NOTE: No input file specified in this run, no data file will be regridded "
				      "and only weight information is calculated.\n");
  }
  else if( nfiles == 1 || nfiles ==2) {
    if( nvector != nvector2 ) mpp_error("fregrid: number of fields specified in u_field must be the same as specified in v_field");
    if( nscalar+nvector==0 ) mpp_error("fregrid: both scalar_field and vector_field are not specified");
    /* when nvector =2 and nscalar=0, nfiles can be 2 otherwise nfiles must be 1 */
    if( nscalar && nfiles != 1 )
      mpp_error("fregrid: when scalar_field is specified, number of files must be 1");
    if( nfiles_out == 0 ) {
      for(i=0; i<nfiles; i++) strcpy(output_file[i], input_file[i]);
    }
    else if (nfiles_out != nfiles )
      mpp_error("fregrid:number of input file is not equal to number of output file");
  }
  else
    mpp_error("fregrid: number of input file should be 1 or 2");

  if(kbegin != 0 || kend != -1) { /* at least one of kbegin and kend is set */
    if(kbegin < 1 || kend < kbegin) mpp_error("fregrid:KlevelBegin should be a positive integer and no larger "
					      "than KlevelEnd when you want pick certain klevel");
  }
  if(lbegin != 0 || lend != -1) { /* at least one of lbegin and lend is set */
     if(lbegin < 1 || lend < lbegin) mpp_error("fregrid:LstepBegin should be a positive integer and no larger "
					      "than LstepEnd when you want pick certain Lstep");
  }
  
  if(nvector > 0) {
    opcode |= VECTOR;
    if(grid_type == AGRID)
      opcode |= AGRID;
    else if(grid_type == BGRID)
      opcode |= BGRID;
  }
  
  /* define history to be the history in the grid file */
  strcpy(history,argv[0]);

  for(i=1;i<argc;i++) {
    strcat(history, " ");
    if(strlen(argv[i]) > MAXENTRY) { /* limit the size of each entry, here we are assume the only entry that is longer than
					MAXENTRY= 256 is the option --scalar_field --u_field and v_field */
      if(strcmp(argv[i-1], "--scalar_field") && strcmp(argv[i-1], "--u_field") && strcmp(argv[i-1], "--v_field") )
	mpp_error("fregrid: the entry ( is not scalar_field, u_field, v_field ) is too long, need to increase parameter MAXENTRY");
      strcat(history, "(**please see the field list in this file**)" );
    }
    else
      strcat(history, argv[i]);
  }
  
  /* get the mosaic information of input and output mosaic*/
  fid = mpp_open(mosaic_in, MPP_READ);
  ntiles_in = mpp_get_dimlen(fid, "ntiles");
  mpp_close(fid);
  if(mosaic_out) {
    fid = mpp_open(mosaic_out, MPP_READ);
    ntiles_out = mpp_get_dimlen(fid, "ntiles");
    mpp_close(fid);
  }
  else
    ntiles_out = 1;

  if(!strcmp(interp_method, "conserve_order1") ) {
    if(mpp_pe() == mpp_root_pe())printf("****fregrid: first order conservative scheme will be used for regridding.\n");
    opcode |= CONSERVE_ORDER1;
  }
  else if(!strcmp(interp_method, "conserve_order2") ) {
    if(mpp_pe() == mpp_root_pe())printf("****fregrid: second order conservative scheme will be used for regridding.\n");
    opcode |= CONSERVE_ORDER2;
  }
  else if(!strcmp(interp_method, "bilinear") ) {
    if(mpp_pe() == mpp_root_pe())printf("****fregrid: bilinear remapping scheme will be used for regridding.\n");  
    opcode |= BILINEAR;
  }
  else
    mpp_error("fregrid: interp_method must be 'conserve_order1', 'conserve_order2' or 'bilinear'");

  if(test_case) {
    if(nfiles != 1) mpp_error("fregrid: when test_case is specified, nfiles should be 1");
    sprintf(output_file[0], "%s.%s.output", test_case, interp_method);
  }

  if(check_conserve) opcode |= CHECK_CONSERVE;
  
  if( opcode & BILINEAR ) {
    int ncontact;
    ncontact = read_mosaic_ncontacts(mosaic_in);
    if( nlon == 0 || nlat == 0) mpp_error("fregrid: when interp_method is bilinear, nlon and nlat should be specified");
    if(ntiles_in != 6) mpp_error("fregrid: when interp_method is bilinear, the input mosaic should be 6 tile cubic grid");
    if(ncontact !=12)  mpp_error("fregrid: when interp_method is bilinear, the input mosaic should be 12 contact cubic grid");
    if(mpp_npes() > 1) mpp_error("fregrid: parallel is not implemented for bilinear remapping");
  }
  else
    y_at_center = 1;


  /* memory allocation for data structure */
  grid_in   = (Grid_config *)malloc(ntiles_in *sizeof(Grid_config));
  grid_out  = (Grid_config *)malloc(ntiles_out*sizeof(Grid_config));
  bound_T   = (Bound_config *)malloc(ntiles_in *sizeof(Bound_config));
  interp    = (Interp_config *)malloc(ntiles_out*sizeof(Interp_config));
  get_input_grid( ntiles_in, grid_in, bound_T, mosaic_in, opcode );
  if(mosaic_out)
    get_output_grid_from_mosaic( ntiles_out, grid_out, mosaic_out, opcode );
  else
    get_output_grid_by_size(ntiles_out, grid_out, lonbegin, lonend, latbegin, latend,
			    nlon, nlat, finer_step, y_at_center, opcode);

   if(remap_file) set_remap_file(ntiles_out, mosaic_out, remap_file, interp, &opcode, save_weight_only);  
  
  if(!save_weight_only) {
    file_in   = (File_config *)malloc(ntiles_in *sizeof(File_config));
    file_out  = (File_config *)malloc(ntiles_out*sizeof(File_config));
 
    if(nfiles == 2) {
      file2_in   = (File_config *)malloc(ntiles_in *sizeof(File_config));
      file2_out  = (File_config *)malloc(ntiles_out*sizeof(File_config));
    }
    if(nscalar > 0) {
      scalar_in  = (Field_config *)malloc(ntiles_in *sizeof(Field_config));
      scalar_out = (Field_config *)malloc(ntiles_out *sizeof(Field_config));
    }
    if(nvector > 0) {
      u_in  = (Field_config *)malloc(ntiles_in *sizeof(Field_config));
      u_out = (Field_config *)malloc(ntiles_out *sizeof(Field_config));    
      v_in  = (Field_config *)malloc(ntiles_in *sizeof(Field_config));
      v_out = (Field_config *)malloc(ntiles_out *sizeof(Field_config));
    }
  
    set_mosaic_data_file(ntiles_in, mosaic_in, dir_in, file_in,  input_file[0]);
    set_mosaic_data_file(ntiles_out, mosaic_out, dir_out, file_out, output_file[0]);
    if(nfiles == 2) {
      set_mosaic_data_file(ntiles_in, mosaic_in, dir_in, file2_in,  input_file[1]);
      set_mosaic_data_file(ntiles_out, mosaic_out, dir_out, file2_out, output_file[1]);    
    }

    for(n=0; n<ntiles_in; n++) file_in[n].fid = mpp_open(file_in[n].name, MPP_READ);

    set_field_struct ( ntiles_in,   scalar_in,   nscalar, scalar_name[0], file_in);
    set_field_struct ( ntiles_out,  scalar_out,  nscalar, scalar_name[0], file_out);
    set_field_struct ( ntiles_in,   u_in,        nvector, u_name[0], file_in);
    set_field_struct ( ntiles_out,  u_out,       nvector, u_name[0], file_out);
    if(nfiles == 1) {
      set_field_struct ( ntiles_in,   v_in,        nvector, v_name[0], file_in);
      set_field_struct ( ntiles_out,  v_out,       nvector, v_name[0], file_out);
    }
    else {
      set_field_struct ( ntiles_in,   v_in,        nvector, v_name[0], file2_in);
      set_field_struct ( ntiles_out,  v_out,       nvector, v_name[0], file2_out);
    }

    get_input_metadata(ntiles_in, nfiles, file_in, file2_in, scalar_in, u_in, v_in, grid_in, kbegin, kend, lbegin, lend, opcode);

    set_output_metadata(ntiles_in, nfiles, file_in, file2_in, scalar_in, u_in, v_in,
			ntiles_out, file_out, file2_out, scalar_out, u_out, v_out, grid_out, history, tagname);
    /* when the interp_method specified through command line is CONSERVE_ORDER1, but the interp_method in the source file
       field attribute is CONSERVE_ORDER2, need to modify the interp_method value */
    if(opcode & CONSERVE_ORDER1) {
      for(l=0; l<nscalar; l++) {
	if(scalar_out->var[l].interp_method == CONSERVE_ORDER2) {
	  if(mpp_pe() == mpp_root_pe())printf("NOTE from fregrid: even though the interp_method specified through command line is "
					      "conserve_order1, the interp_method is reset to conserve_order2 because some fields in "
					      "the source data have interp_method attribute value conserve_order2");
	  opcode = opcode & ~CONSERVE_ORDER1;
	  opcode |= CONSERVE_ORDER2;
	  break;
	}
      }
    }
    if(opcode & CONSERVE_ORDER1) {
      for(l=0; l<nvector; l++) {
	if(u_out->var[l].interp_method == CONSERVE_ORDER2) {
	  if(mpp_pe() == mpp_root_pe())printf("NOTE from fregrid: even though the interp_method specified through command line is "
					      "conserve_order1, the interp_method is reset to conserve_order2 because some fields in "
					      "the source data have interp_method attribute value conserve_order2");
	  opcode = opcode & ~CONSERVE_ORDER1;
	  opcode |= CONSERVE_ORDER2;
	  break;
	}
      }
    }    
  }
  
  /* preparing for the interpolation, if remapping information exist, read it from remap_file,
     otherwise create the remapping information and write it to remap_file
  */
   if( opcode & BILINEAR ) /* bilinear interpolation from cubic to lalon */
     setup_bilinear_interp(ntiles_in, grid_in, ntiles_out, grid_out, interp, opcode );
   else
     setup_conserve_interp(ntiles_in, grid_in, ntiles_out, grid_out, interp, opcode);
  
   if(save_weight_only) {
     if(mpp_pe() == mpp_root_pe() ) {
       printf("NOTE: Successfully running fregrid and the following files which store weight information are generated.\n");
       for(n=0; n<ntiles_out; n++) {
	 printf("****%s\n", interp[n].remap_file);
       }
     }
     mpp_end();
     return 0;     
   }
  
   if(nscalar > 0) {
     get_field_attribute(ntiles_in, scalar_in);
     copy_field_attribute(ntiles_out, scalar_in, scalar_out);
   }
   
   if(nvector > 0) {
     get_field_attribute(ntiles_in, u_in);
     get_field_attribute(ntiles_in, v_in);
     copy_field_attribute(ntiles_out, u_in, u_out);
     copy_field_attribute(ntiles_out, v_in, v_out);
   }


  
   /* set time step to 1, only test scalar field now, nz need to be 1 */
   if(test_case) {
     if(nscalar != 1 || nvector != 0) mpp_error("fregrid: when test_case is specified, nscalar must be 1 and nvector must be 0");
     if(scalar_in->var->nz != 1) mpp_error("fregrid: when test_case is specified, number of vertical level must be 1");
     file_in->nt = 1;
     file_out->nt = 1;
   }
   
  /* Then doing the regridding */
  for(m=0; m<file_in->nt; m++) {
    int memsize, level_z, level_n, level_t;

    write_output_time(ntiles_out, file_out, m);
    if(nfiles > 1) write_output_time(ntiles_out, file2_out, m);
    
    /* first interp scalar variable */
    for(l=0; l<nscalar; l++) {
      if( !scalar_in->var[l].has_taxis && m>0) continue;
      level_t = m + scalar_in->var[l].lstart;
      /*--- to reduce memory usage, we are only do remapping for on horizontal level one time */
      for(level_n =0; level_n < scalar_in->var[l].nn; level_n++)
	for(level_z=scalar_in->var[l].kstart; level_z <= scalar_in->var[l].kend; level_z++)
	  {	    
	    if(test_case)
	      get_test_input_data(test_case, test_param, ntiles_in, scalar_in, grid_in, bound_T, opcode);
	    else
	      get_input_data(ntiles_in, scalar_in, grid_in, bound_T, l, level_z, level_n, level_t);
	    allocate_field_data(ntiles_out, scalar_out, grid_out);
	    if( opcode & BILINEAR ) 
	      do_scalar_bilinear_interp(interp, l, ntiles_in, grid_in, grid_out, scalar_in, scalar_out, finer_step, fill_missing);
	    else
	      do_scalar_conserve_interp(interp, l, ntiles_in, grid_in, ntiles_out, grid_out, scalar_in, scalar_out, opcode);
	    write_field_data(ntiles_out, scalar_out, grid_out, l, level_z, level_n, m);
	    if(scalar_out->var[l].interp_method == CONSERVE_ORDER2) {
	      for(n=0; n<ntiles_in; n++) {
		free(scalar_in[n].grad_x);
		free(scalar_in[n].grad_y);
		if(scalar_in[n].var[l].has_missing) free(scalar_in[n].grad_mask);
	      }
	    }
	    for(n=0; n<ntiles_in; n++) free(scalar_in[n].data);
	    for(n=0; n<ntiles_out; n++) free(scalar_out[n].data);
	  }
    }

    /* then interp vector field */
    for(l=0; l<nvector; l++) {
      if( !u_in[n].var[l].has_taxis && m>0) continue;
      level_t = m + u_in->var[l].lstart;
      get_input_data(ntiles_in, u_in, grid_in, bound_T, l, level_z, level_n, level_t);
      get_input_data(ntiles_in, v_in, grid_in, bound_T, l, level_z, level_n, level_t);
      allocate_field_data(ntiles_out, u_out, grid_out);
      allocate_field_data(ntiles_out, v_out, grid_out);
      if( opcode & BILINEAR )
	do_vector_bilinear_interp(interp, l, ntiles_in, grid_in, ntiles_out, grid_out, u_in, v_in, u_out, v_out, finer_step, fill_missing);
      else
	do_vector_conserve_interp(interp, l, ntiles_in, grid_in, ntiles_out, grid_out, u_in, v_in, u_out, v_out, opcode);
      
      write_field_data(ntiles_out, u_out, grid_out, l, level_z, level_n, m);
      write_field_data(ntiles_out, v_out, grid_out, l, level_z, level_n, m);
      for(n=0; n<ntiles_in; n++) {
	free(u_in[n].data);
	free(v_in[n].data);
      }
      for(n=0; n<ntiles_out; n++) {
	free(u_out[n].data);
	free(v_out[n].data);
      }      
    }
  }

  if(mpp_pe() == mpp_root_pe() ) {
    printf("Successfully running fregrid and the following output file are generated.\n");
    for(n=0; n<ntiles_out; n++) {
      mpp_close(file_out[n].fid);
      printf("****%s\n", file_out[n].name);
      if( nfiles > 1 ) {
	mpp_close(file2_out[n].fid);
	printf("****%s\n", file2_out[n].name);
      }
    }
  }
      
  mpp_end();
  return 0;
  
} /* end of main */
Beispiel #6
0
int mpp_open(const char *file, int action) {
  char curfile[128];
  char errmsg[512];  
  int ncid, status, istat, n, fid;
  size_t blksz=65536;
  
  /* write only from root pe. */
  if(action == MPP_WRITE && mpp_pe() != mpp_root_pe() ) return -1;
  /*if file is not ended with .nc add .nc at the end. */
  strcpy(curfile, file);
  if(strstr(curfile, ".nc") == NULL) strcat(curfile,".nc");

  /* look through currently files to make sure the file is not in the list*/
  fid = -1;
  for(n=0; n<nfiles; n++) {
    if(!strcmp(files[n].name, file)) {
      fid = n;
      break;
    }
  }
  if(fid > -1) {
    if(files[n].action == MPP_WRITE) {
      sprintf( errmsg, "mpp_io(mpp_open): %s is already created for write", file);
      mpp_error(errmsg);
    }
    if(files[n].status) {
      sprintf( errmsg, "mpp_io(mpp_open): %s is already opened", file);
      mpp_error(errmsg);
    }
  }
  else {
    fid = nfiles;
    nfiles++;
    if(nfiles > MAXFILE) mpp_error("mpp_io(mpp_open): nfiles is larger than MAXFILE, increase MAXFILE");
    strcpy(files[fid].name, file);
    files[fid].nvar = 0;
    files[fid].var = (VarType *)malloc(MAXVAR*sizeof(VarType));
  }
    
  switch (action) {
  case MPP_WRITE:
    switch (in_format) {
      case NC_FORMAT_NETCDF4:
        status = nc__create(curfile, NC_NETCDF4, 0, &blksz, &ncid);
        break;
      case NC_FORMAT_NETCDF4_CLASSIC:
        status = nc__create(curfile, NC_NETCDF4 | NC_CLASSIC_MODEL, 0, &blksz, &ncid);
        break;
      case NC_FORMAT_64BIT:
        status = nc__create(curfile, NC_CLOBBER | NC_64BIT_OFFSET, 0, &blksz, &ncid);
        break;
      case NC_FORMAT_CLASSIC:
        status = nc__create(curfile, NC_CLOBBER | NC_CLASSIC_MODEL, 0, &blksz, &ncid);
        break;
      default:
        sprintf(errmsg, "mpp_io(mpp_open): Unknown netCDF format");
        mpp_error(errmsg);
    }
    break;
  case MPP_APPEND:
    status = nc_open(curfile, NC_WRITE, &ncid);
    break;
  case MPP_READ:
    status = nc_open(curfile,NC_NOWRITE, &ncid);
    istat = nc_inq_format(ncid,&in_format);
    break;
  default:
    sprintf(errmsg, "mpp_io(mpp_open): the action should be MPP_WRITE or MPP_READ when opening file %s", file);
    mpp_error(errmsg);
  }
  
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_open): error in opening file %s", file);
    netcdf_error(errmsg, status);
  }

  files[fid].ncid   = ncid;
  files[fid].status = 1;
  files[fid].action = action;
  
  return fid;
}
Beispiel #7
0
int main(int argc, char* argv[])
{
  char   *mosaic_file = NULL, *topog_file = NULL, *topog_field = NULL;
  char   topog_type[32] = "realistic", output_file[32] = "topog.nc";
  int    num_filter_pass = 1;
  int    x_refine = 2, y_refine = 2;
  double 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    jwest_south=0, jwest_north=0, jeast_south=0, jeast_north=0;
  double dome_slope=0.01;
  double dome_bottom=3600.0;
  double dome_embayment_west=19.0; 
  double dome_embayment_east=21.0;
  double dome_embayment_south=69.0;
  double dome_embayment_depth=600.0;
  char   *vgrid_file = NULL;
  int    full_cell = 0;
  int    fill_isolated_cells = 1;
  int    dont_change_landmask = 0;
  int    kmt_min = 2;
  int    adjust_topo = 1;
  double fraction_full_cell = 0.2;
  int    open_very_this_cell = 1;
  double min_thickness = 0.1;
  int    my_topog_type;
  int    use_great_circle_algorithm=0;
  int    cyclic_x, cyclic_y, tripolar_grid;
  int    errflg = (argc == 1);
  int    option_index, i, c;
  unsigned int verbose = 0;
  
  /*
   * 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'},
    {"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'},
    {"output",                      required_argument, NULL, 'o'},
    {"jwest_south",                 required_argument, NULL, 'A'},
    {"jwest_north",                 required_argument, NULL, 'B'},
    {"jeast_south",                 required_argument, NULL, 'C'},
    {"jeast_north",                 required_argument, NULL, 'D'},
    {"dome_slope",                  required_argument, NULL, 'E'},
    {"dome_bottom",                 required_argument, NULL, 'F'},
    {"dome_embayment_west",         required_argument, NULL, 'G'},
    {"dome_embayment_east",         required_argument, NULL, 'H'},
    {"dome_embayment_south",        required_argument, NULL, 'I'},
    {"dome_embayment_depth",        required_argument, NULL, 'J'},
    {"vgrid_file",                  required_argument, NULL, 'K'},
    {"flat_bottom",                 no_argument,       NULL, 'L'},
    {"full_cell",                   no_argument,       NULL, 'M'},
    {"dont_fill_isolated_cells",    no_argument,       NULL, 'N'},
    {"dont_change_landmask",        no_argument,       NULL, 'O'},
    {"kmt_min",                     required_argument, NULL, 'P'},
    {"dont_adjust_topo",            no_argument,       NULL, 'Q'},
    {"fraction_full_cell",          required_argument, NULL, 'R'},
    {"dont_open_very_this_cell",    no_argument,       NULL, 'S'},
    {"min_thickness",               required_argument, NULL, 'T'},
    {"help",                        no_argument,       NULL, 'h'},
    {"verbose",                     no_argument,       NULL, 'V'},
    {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 '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(output_file,optarg);
      break;
    case 'A':
      jwest_south = atoi(optarg);
      break;
    case 'B':
      jwest_north = atoi(optarg);
      break;
    case 'C':
      jeast_south = atoi(optarg);
      break;
    case 'D':
      jeast_north = atoi(optarg);
      break;
    case 'E':
      dome_slope = atof(optarg);
      break;
    case 'F':
      dome_bottom = atof(optarg);
      break;
    case 'G':
      dome_embayment_west = atof(optarg);
      break;
    case 'H':
      dome_embayment_east = atof(optarg);
      break;
    case 'I':
      dome_embayment_south = atof(optarg);
      break;
    case 'J':
      dome_embayment_depth = atof(optarg);
      break;
    case 'K':
      vgrid_file = optarg;
      break;
    case 'L':
      flat_bottom = 1;
      break;
    case 'M':
      full_cell = 1;
      break;
    case 'N':
      fill_isolated_cells = 0;
      break;
    case 'O':
      dont_change_landmask = 1;
      break;
    case 'P':
      kmt_min = atoi(optarg);
      break;
    case 'Q':
      adjust_topo = 0;
      break;
    case 'R':
      fraction_full_cell = atof(optarg);
      break;
    case 'S':
      open_very_this_cell = 0;
      break;
    case 'T':
      min_thickness = atof(optarg);
      break;
    case 'V':
      verbose = 1;
      break;      
    case '?':
      errflg++;
      break;
    }

  if (errflg || !mosaic_file ) {
    if( mpp_pe() == mpp_root_pe() ) {
      char **u = usage;
      while (*u) { fprintf(stderr, "%s\n", *u); u++; }
      mpp_error("make_topog: Check your arguments");
    }
  }


  /* Write out arguments value  */
  if(mpp_pe() == mpp_root_pe() && verbose) 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() && verbose) printf("NOTE from make_topog ==> x_refine is %d, y_refine is %d\n",
				       x_refine, y_refine);

  /* vgrid_file can only be passed in when topog_type is realistic */ 
  if(vgrid_file && strcmp(topog_type,"realistic"))
      mpp_error("make_topog: --vgrid_file should not be specified when topog_type = realistic");

  if (strcmp(topog_type,"rectangular_basin") == 0) {
    my_topog_type = RECTANGULAR_BASIN;
    if(mpp_pe() == mpp_root_pe() && verbose) printf("NOTE from make_topog ==> the basin depth is %f\n",bottom_depth);
  }
  else if (strcmp(topog_type,"gaussian") == 0) {
    my_topog_type = GAUSSIAN;
    if(mpp_pe() == mpp_root_pe() && verbose){
      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) {
    my_topog_type = BOWL;
    if(mpp_pe() == mpp_root_pe() && verbose){
      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) {
    my_topog_type = IDEALIZED;
    if(mpp_pe() == mpp_root_pe() && verbose){
      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) {
    my_topog_type = REALISTIC;
    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() && verbose){
      printf("\n\n ************************************************************\n\n");
      printf("NOTE from make_topog ==> input arguments\n\n");
      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);
      printf("NOTE from make_topog ==> kmt_min is %d\n", kmt_min);
      printf("NOTE from make_topog ==> fraction_full_cell is %f\n", fraction_full_cell);
      printf("NOTE from make_topog ==> min_thickness is %f\n", min_thickness);
      if(vgrid_file)
	printf("NOTE from make_topog ==> vgrid_file is %s\n", vgrid_file);
      else
	printf("NOTE from make_topog ==> no vgrid_file is specified\n");
      
      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");
      if(flat_bottom) printf("NOTE from make_topog ==> generate flat bottom over ocean points.\n");
      if(full_cell) printf("NOTE from make_topog ==> not generate partial bottom cells.\n");
      if(fill_isolated_cells) printf("NOTE from make_topog ==> not allow non-advective tracer cells\n");
      if(dont_change_landmask) printf("NOTE from make_topog ==> not change land/sea mask when filling isolated cells\n");
      if(open_very_this_cell) printf("NOTE from make_topog ==> open this cell\n");
      if(adjust_topo) printf("NOTE from make_topog ==> adjust topography\n");
      printf("\n\n ************************************************************\n\n");
    }
  }
  else if(strcmp(topog_type,"box_channel") == 0) {
    my_topog_type = BOX_CHANNEL;
    if( jwest_south <= 0) mpp_error("make_topog: jwest_south must a positive integer when topog_type = box_channel");
    if( jwest_north <= 0) mpp_error("make_topog: jwest_north must a positive integer when topog_type = box_channel");
    if( jeast_south <= 0) mpp_error("make_topog: jeast_south must a positive integer when topog_type = box_channel");
    if( jeast_north <= 0) mpp_error("make_topog: jeast_north must a positive integer when topog_type = box_channel");
    if( jwest_south > jwest_north ) mpp_error("make_topog: jwest_south > jwest_north when topog_type = box_channel");
    if( jeast_south > jeast_north ) mpp_error("make_topog: jeast_south > jeast_north when topog_type = box_channel");
  }
  else if(strcmp(topog_type,"dome") == 0) {
    my_topog_type = DOME;
  }
  else {
    mpp_error("make_topog: topog_type should be rectangular_basin, gaussian, bowl, idealized, realistic, box_channel or dome");
  }
  
  if(mpp_pe() == mpp_root_pe() && verbose) {
    printf("**************************************************\n");
    printf("Begin to generate topography \n");
  }

  {
    const int STRING = 255;
    int m_fid, g_fid, vid;
    int ntiles, fid, dim_ntiles, n, dims[2];
    size_t start[4], nread[4], nwrite[4];
    int *nx=NULL, *ny=NULL, *nxp=NULL, *nyp=NULL;
    int *id_depth=NULL, *id_level=NULL;
    double *depth=NULL, *x=NULL, *y=NULL;
    int *num_levels=NULL;
    char **tile_files=NULL;
    char history[512], dimx_name[128], dimy_name[128], depth_name[128], level_name[128];
    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(double *));
    id_depth = (int *)malloc(ntiles*sizeof(int));
    id_level = (int *)malloc(ntiles*sizeof(int));
    /* loop through each tile to get tile information and set up meta data for output file */
    fid = mpp_open(output_file, MPP_WRITE);

    dim_ntiles = mpp_def_dim(fid, "ntiles", ntiles);
    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++ ) {
      int use_great_circle_algorithm_prev=0;
      
      tile_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, "gridfiles");
      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);
      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;
      if(ntiles == 1) {
	strcpy(dimx_name, "nx");
	strcpy(dimy_name, "ny");
	strcpy(depth_name, "depth");
	if(vgrid_file)strcpy(level_name, "num_levels");
      }
      else {
	sprintf(dimx_name, "nx_tile%d", n+1);
	sprintf(dimy_name, "ny_tile%d", n+1);
	sprintf(depth_name, "depth_tile%d", n+1);
	if(vgrid_file)sprintf(level_name, "num_levels_tile%d", n+1);
      }

      dims[1] = mpp_def_dim(fid, dimx_name, nx[n]); 
      dims[0] = mpp_def_dim(fid, dimy_name, ny[n]);
      id_depth[n] = mpp_def_var(fid, depth_name, NC_DOUBLE, 2, dims,  2, "standard_name",
				"topographic depth at T-cell centers", "units", "meters");
      if(vgrid_file) id_level[n] = mpp_def_var(fid, level_name, NC_INT, 2, dims, 2, "standard_name",
					       "number of vertical T-cells", "units", "none");
      /* when topog_type is realistics, check if use great_circle_algorithm */
      use_great_circle_algorithm = get_great_circle_algorithm(g_fid);
      if(n>0) {
	if( use_great_circle_algorithm != use_great_circle_algorithm_prev)
	  mpp_error("make_topog: atribute 'great_circle_algorithm' of field 'tile' have different value for different tile");
      }
      use_great_circle_algorithm_prev = use_great_circle_algorithm;

      mpp_close(g_fid);
    }
    mpp_close(m_fid);
    mpp_def_global_att(fid, "grid_version", grid_version);
    mpp_def_global_att(fid, "code_version", tagname);
    if(use_great_circle_algorithm) mpp_def_global_att(fid, "great_circle_algorithm", "TRUE");
    mpp_def_global_att(fid, "history", history);
    
    mpp_end_def(fid);

    if(mpp_pe()==mpp_root_pe() && use_great_circle_algorithm)
      printf("\n NOTE from make_topog: use great circle algorithm\n");
    
    /* get the boundary condition for realistics topogrpahy, currently only support tripolar_grid,
     cyclic_x and cyclic_y*/
    if(my_topog_type == REALISTIC) get_boundary_type(mosaic_file, VERSION_2, &cyclic_x, &cyclic_y, &tripolar_grid);
    
    /* 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=NULL, *tmp=NULL;
      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;

      if(my_topog_type == DOME ) {
	x   = (double *)malloc(nxc*nyc*sizeof(double));
	y   = (double *)malloc(nxc*nyc*sizeof(double));
      }
      else {
	x   = (double *)malloc((nxc+1)*(nyc+1)*sizeof(double));
	y   = (double *)malloc((nxc+1)*(nyc+1)*sizeof(double));
      }
      depth = (double *)malloc(nxc*nyc*sizeof(double));
      if(vgrid_file) num_levels = (int* )malloc(nxc*nyc*sizeof(int)); 
      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);
      if(my_topog_type == DOME ) {
	for(j = 0; j < nyc; j++) for(i = 0; i < nxc; i++)
	  x[j*nxc+i] = tmp[(j*y_refine+1)*ni+i*x_refine+1];
      }
      else {
	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);
      if(my_topog_type == DOME ) {
	for(j = 0; j < nyc; j++) for(i = 0; i < nxc; i++)
	  y[j*nxc+i] = tmp[(j*y_refine+1)*ni+i*x_refine+1];
      }
      else {
	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];
      }
      switch (my_topog_type) {
      case RECTANGULAR_BASIN:
	create_rectangular_topog(nx[n], ny[n], bottom_depth, depth);
	break;
      case GAUSSIAN:
	create_gaussian_topog(nx[n], ny[n], x, y, bottom_depth, min_depth,
			      gauss_amp, gauss_scale, slope_x, slope_y, depth);
	break;
      case BOWL:
	create_bowl_topog(nx[n], ny[n], x, y, bottom_depth, min_depth, bowl_east,
			  bowl_south, bowl_west, bowl_north, depth);
	break;
      case IDEALIZED:
	create_idealized_topog( nx[n], ny[n], x, y, bottom_depth, min_depth, depth);
	break;
      case REALISTIC:	
	create_realistic_topog(nxc, nyc, x, y, vgrid_file, topog_file, topog_field, scale_factor,
			       tripolar_grid, cyclic_x, cyclic_y, fill_first_row, filter_topog, num_filter_pass,
			       smooth_topo_allow_deepening, round_shallow, fill_shallow,
			       deepen_shallow, full_cell, flat_bottom, adjust_topo,
			       fill_isolated_cells, dont_change_landmask, kmt_min, min_thickness, open_very_this_cell,
			       fraction_full_cell, depth, num_levels, domain, verbose, use_great_circle_algorithm );
	break;
      case BOX_CHANNEL:
	create_box_channel_topog(nx[n], ny[n], bottom_depth,
				 jwest_south, jwest_north, jeast_south, jeast_north, depth);
	break;
      case DOME:
	create_dome_topog(nx[n], ny[n], x, y, dome_slope, dome_bottom, dome_embayment_west,
			  dome_embayment_east, dome_embayment_south, dome_embayment_depth, depth);
	break;
      }
      gdata = (double *)malloc(nx[n]*ny[n]*sizeof(double));
      mpp_global_field_double(domain, nxc, nyc, depth, gdata);
      mpp_put_var_value(fid, id_depth[n], gdata);
      if(vgrid_file) {
	double *tmp_double=NULL;
	int    *gdata_int=NULL;
	tmp_double = (double *)malloc(nxc*nyc*sizeof(double));
	gdata_int = (int *)malloc(nx[n]*ny[n]*sizeof(int));
	for(i=0; i<nxc*nyc; i++) tmp_double[i] = num_levels[i];
	mpp_global_field_double(domain, nxc, nyc, tmp_double, gdata);
	for(i=0; i<nx[n]*ny[n]; i++) gdata_int[i] = gdata[i];
	mpp_put_var_value(fid, id_level[n], gdata_int);
	free(gdata_int);
	free(tmp_double);
	free(num_levels);
      }
      free(x);
      free(y);
      free(tmp);
      free(depth);
      free(gdata);
      mpp_delete_domain2d(&domain);
    }
    mpp_close(fid);
  
    /*release memory */
    free(id_depth);
    free(id_level);
    for(n=0; n<ntiles; n++) free(tile_files[n]);
    free(tile_files);
    free(nx);
    free(ny);
    free(nxp);
    free(nyp);
  }
    
  if(mpp_pe() == mpp_root_pe() && verbose ) printf("Successfully generate %s\n",output_file);

  mpp_end();

  return 0;
}; //main
Beispiel #8
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 */
Beispiel #9
0
/*******************************************************************************
 void do_scalar_conserve_interp( )
 doing conservative interpolation
*******************************************************************************/
void do_scalar_conserve_interp(Interp_config *interp, int varid, int ntiles_in, const Grid_config *grid_in,
			       int ntiles_out, const Grid_config *grid_out, const Field_config *field_in,
			       Field_config *field_out, unsigned int opcode)
{
  int nx1, ny1, nx2, ny2, i1, j1, i2, j2, tile, n, m, i, j, n1, n2;
  int has_missing, halo, interp_method;
  double area, missing, di, dj;
  double *out_area;

  interp_method = field_in->var[varid].interp_method;
  halo = 0;
  if(interp_method == CONSERVE_ORDER2) halo = 1;
  
  missing = field_in->var[varid].missing;
  has_missing = field_in->var[varid].has_missing;
  
  for(m=0; m<ntiles_out; m++) {
    nx2 = grid_out[m].nxc;
    ny2 = grid_out[m].nyc;
    out_area = (double *)malloc(nx2*ny2*sizeof(double));
    
    for(i=0; i<nx2*ny2; i++) field_out[m].data[i] = 0.0;
    
    for(i=0; i<nx2*ny2; i++) out_area[i] = 0.0;
    if(interp_method == CONSERVE_ORDER1) {
      if(has_missing) {
	for(n=0; n<interp[m].nxgrid; n++) {
	  i2   = interp[m].i_out[n];
	  j2   = interp[m].j_out[n];
	  i1   = interp[m].i_in [n];
	  j1   = interp[m].j_in [n];    
	  tile = interp[m].t_in [n];
	  area = interp[m].area [n];
	  nx1  = grid_in[tile].nx;
	  ny1  = grid_in[tile].ny;
	  if( field_in[tile].data[j1*nx1+i1] != missing ) {
	    field_out[m].data[j2*nx2+i2] += field_in[tile].data[j1*nx1+i1]*area;
	    out_area[j2*nx2+i2] += area;
	  }
	}
      }
      else {
	for(n=0; n<interp[m].nxgrid; n++) {
	  i2   = interp[m].i_out[n];
	  j2   = interp[m].j_out[n];
	  i1   = interp[m].i_in [n];
	  j1   = interp[m].j_in [n];    
	  tile = interp[m].t_in [n];
	  area = interp[m].area [n];
	  nx1  = grid_in[tile].nx;
	  ny1  = grid_in[tile].ny;
	  field_out[m].data[j2*nx2+i2] += field_in[tile].data[j1*nx1+i1]*area;
	  out_area[j2*nx2+i2] += area;
	}
      }	  
    }
    else {
      if(has_missing) {
	for(n=0; n<interp[m].nxgrid; n++) {
	  i2   = interp[m].i_out[n];
	  j2   = interp[m].j_out[n];
	  i1   = interp[m].i_in [n];
	  j1   = interp[m].j_in [n];
	  di   = interp[m].di_in[n];
	  dj   = interp[m].dj_in[n];
	  tile = interp[m].t_in [n];
	  area = interp[m].area [n];
	  nx1  = grid_in[tile].nx;
	  ny1  = grid_in[tile].ny;
	  n2 = (j1+1)*(nx1+2)+i1+1;
	  if( field_in[tile].data[n2] != missing ) {
	    n1 = j1*nx1+i1;
	    if(field_in[tile].grad_mask[n1]) { /* use zero gradient */
	      field_out[m].data[j2*nx2+i2] += field_in[tile].data[n2]*area;
	    }
	    else {
	      field_out[m].data[j2*nx2+i2] += (field_in[tile].data[n2]+field_in[tile].grad_x[n1]*di
						  +field_in[tile].grad_y[n1]*dj)*area;
	    }
	    out_area[j2*nx2+i2] += area;
	  }
	}
      }
      else {
	for(n=0; n<interp[m].nxgrid; n++) {
	  i2   = interp[m].i_out[n];
	  j2   = interp[m].j_out[n];
	  i1   = interp[m].i_in [n];
	  j1   = interp[m].j_in [n];
	  di   = interp[m].di_in[n];
	  dj   = interp[m].dj_in[n];
	  tile = interp[m].t_in [n];
	  area = interp[m].area [n];
	  nx1  = grid_in[tile].nx;
	  ny1  = grid_in[tile].ny;
	  n1 = j1*nx1+i1;
	  n2 = (j1+1)*(nx1+2)+i1+1;
	  field_out[m].data[j2*nx2+i2] += (field_in[tile].data[n2]+field_in[tile].grad_x[n1]*di
					      +field_in[tile].grad_y[n1]*dj)*area;
	  out_area[j2*nx2+i2] += area;
	}
      }
    }
    if(opcode & TARGET) {
      for(i=0; i<nx2*ny2; i++) {
	if(out_area[i] > 0)
	  field_out[m].data[i] /= grid_out[m].area[i];
	else
	  field_out[m].data[i] = missing;
      }
    }
    else {
      for(i=0; i<nx2*ny2; i++) {
	if(out_area[i] > 0)
	  field_out[m].data[i] /= out_area[i];
	else
	  field_out[m].data[i] = missing;
      }      
    }
  }

  free(out_area);

  /* conservation check if needed */
  if(opcode & CHECK_CONSERVE) {
    double gsum_in, gsum_out, dd;
    double *area;
    gsum_in = 0;
    gsum_out = 0;
    for(n=0; n<ntiles_in; n++) {
      nx1  = grid_in[n].nx;
      ny1  = grid_in[n].ny;
      area = (double *)malloc(nx1*ny1*sizeof(double));
      get_grid_area(&nx1, &ny1, grid_in[n].lonc, grid_in[n].latc, area);
      
      for(j=0; j<ny1; j++) for(i=0; i<nx1; i++) {
	dd = field_in[n].data[(j+halo)*(nx1+2*halo)+i+halo];
	if(dd != missing) gsum_in += dd*area[j*nx1+i];
      }
      free(area);
    }
    for(n=0; n<ntiles_out; n++) {
      nx2  = grid_out[n].nxc;
      ny2  = grid_out[n].nyc;
      area = (double *)malloc(nx2*ny2*sizeof(double));
      get_grid_area(&nx2, &ny2, grid_out[n].lonc, grid_out[n].latc, area);
      
      for(j=0; j<ny2; j++) for(i=0; i<nx2; i++) {
	dd = field_out[n].data[j*nx2+i];
	if(dd != missing) gsum_out += dd*area[j*nx2+i];
      }
      free(area);
    }
    mpp_sum_double(1, &gsum_out);
    
    if(mpp_pe() == mpp_root_pe()) printf("the flux(data*area) sum of %s: input = %g, output = %g, diff = %g. \n",
					 field_in->var[varid].name, gsum_in, gsum_out, gsum_out-gsum_in);
        

    
  }
  
  
}; /* do_scalar_conserve_interp */
Beispiel #10
0
int main(int argc, char* argv[])
{
  char   *mosaic_file = NULL, *topog_file = NULL, *topog_field = NULL;
  char   topog_type[32] = "realistic", output_file[32] = "topog.nc";
  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;
  int ret;
  
  /*
   * 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'},
    {"output",                      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(output_file,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);

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

  if ((ret = gs_make_topog(history, mosaic_file, topog_type, x_refine, y_refine, 
                           basin_depth,  topog_file, bottom_depth, min_depth, scale_factor, 
                           num_filter_pass, gauss_amp, gauss_scale, slope_x, slope_y, 
                           bowl_south, bowl_north, bowl_west, bowl_east, fill_first_row, 
                           filter_topog, round_shallow, fill_shallow, deepen_shallow,
                           smooth_topo_allow_deepening, output_file)))
     return ret;

    
  if(mpp_pe() == mpp_root_pe() ) printf("Successfully generate %s\n",output_file);

  mpp_end();

  return 0;
}; //main
Beispiel #11
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
Beispiel #12
0
int main(int argc, char* argv[])
{
  int nbnds, n1, n2, i, nk;
  double bnds[MAXBOUNDS];
  int    nz[MAXBOUNDS-1];
  char gridname[128]= "vertical_grid";
  char filename[128];
  double *zeta;
  char center[32] = "none";
  char entry[512];
  char history[256];
  int errflg, c, option_index = 0;
  static struct option long_options[]= {  
    {"nbnds",    required_argument, NULL, 'n'},
    {"bnds",     required_argument, NULL, 'b'},
    {"nz",       required_argument, NULL, 'z'},
    {"grid_name",required_argument, NULL, 'o'},        
    {"center",   required_argument, NULL, 'c'},    
    {0, 0, 0, 0}
  };
  
    /*
   * process command line
   */
  errflg = argc <4;
  nbnds = 0;
  n1 = 0;
  n2 = 0;
  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1)
    switch (c) {
    case 'n':
      nbnds = atoi(optarg);
      break;
    case 'b':
      strcpy(entry, optarg);
      n1 = get_double_entry(entry, bnds);
      break;
    case 'z':
      strcpy(entry, optarg);
      n2 = get_int_entry(entry, nz);
      break;
    case 'o':
      strcpy(gridname, optarg);
      break;
    case 'c':
      strcpy(center, optarg);
      break;
    case '?':
      errflg++;      
    }

  if (errflg ) {
    char **u = usage;
    while (*u) { fprintf(stderr, "%s\n", *u); u++; }
    mpp_error("Wrong usage of this program, check arguments") ;
  }    

  /* check the command-line arguments to make sure the value are suitable */
  if( nbnds < 2 ) mpp_error("number of bounds specified through -nbnd should be an integer greater than 1");
  if( nbnds != n1 ) mpp_error("nbnds does not equal number entry specified through -bnd");
  if( nbnds-1 != n2 ) mpp_error("nbnds-1 does not match number entry specified through -nz");

  /* generate grid */
  nk = 0;
  for(i=0; i<nbnds-1; i++) nk += nz[i];
  zeta = (double *)malloc((nk+1)*sizeof(double));
  create_vgrid(nbnds, bnds, nz, zeta, center);

  /* define history to be the history in the grid file */
  strcpy(history,argv[0]);

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

  sprintf(filename, "%s.nc", gridname);
  
  /* write out vertical grid into a netcdf file */
  {
    int fid, dim, varid;
    
    fid = mpp_open(filename, MPP_WRITE);
    dim  = mpp_def_dim(fid, NZV_NAME, nk+1);
    varid = mpp_def_var(fid, ZETA_NAME, NC_DOUBLE, 1, &dim, 2, "standard_name", "vertical_grid_vertex",
			"units", "meters");
    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);    
    mpp_end_def(fid);
    mpp_put_var_value(fid, varid, zeta);
  
    mpp_close(fid);
  }

  if(mpp_pe() == mpp_root_pe()) printf("Successfully generate vertical grid file %s\n", filename);
  
  mpp_end();

  return 0;
}    
Beispiel #13
0
int main(int argc, char* argv[])
{
  int  nratio = 1;
  int  ndivx[] = {1,1,1,1,1,1};
  int  ndivy[] = {1,1,1,1,1,1};
  char method[32] = "conformal";
  char orientation[32] = "center_pole";
  int  nxbnds=2, nybnds=2, nxbnds0=0, nybnds0=0, nxbnds1=0, nybnds1=0, nxbnds2=0, nybnds2=0;
  double xbnds[MAXBOUNDS], ybnds[MAXBOUNDS];
  int nlon[MAXBOUNDS-1], nlat[MAXBOUNDS-1];
  char grid_type[128]="regular_lonlat_grid";
  char my_grid_file[MAXBOUNDS][STRINGLEN];
  double lat_join=65.;
  double simple_dx=0, simple_dy=0;
  int nx, ny, nxp, nyp, ntiles=1, ntilex=0, ntiley=0, ntiles_file;
  double *x=NULL, *y=NULL, *dx=NULL, *dy=NULL, *angle_dx=NULL, *angle_dy=NULL, *area=NULL;
  
  char history[2560];
  char gridname[32] = "horizontal_grid";
  char center[32] = "none";
  char geometry[32] = "spherical";
  char projection[32] = "none";
  char arcx[32] = "small_circle";
  char north_pole_tile[32] = "0.0 90.0";
  char north_pole_arcx[32] = "0.0 90.0";
  char discretization[32]  = "logically_rectangular";
  char conformal[32]       = "true";
  char mesg[256], str[128];
  char entry[MAXBOUNDS*STRINGLEN];
  int isc, iec, jsc, jec, nxc, nyc, layout[2];
  domain2D domain;
  int n, errflg, c, i;  
  int option_index;

  static struct option long_options[] = {
    {"grid_type",       required_argument, NULL, 'a'},
    {"my_grid_file",    required_argument, NULL, 'b'},
    {"nxbnds",          required_argument, NULL, 'c'},
    {"nybnds",          required_argument, NULL, 'd'},
    {"xbnds",           required_argument, NULL, 'e'},
    {"ybnds",           required_argument, NULL, 'f'},
    {"nlon",            required_argument, NULL, 'g'},
    {"nlat",            required_argument, NULL, 'i'},
    {"lat_join",        required_argument, NULL, 'j'},
    {"nratio",          required_argument, NULL, 'k'},
    {"simple_dx",       required_argument, NULL, 'l'},
    {"simple_dy",       required_argument, NULL, 'm'},
    {"ndivx",           required_argument, NULL, 'o'},
    {"ndivy",           required_argument, NULL, 'p'},
    {"grid_name",       required_argument, NULL, 'q'},
    {"center",          required_argument, NULL, 'r'},
    {"help",            no_argument,       NULL, 'h'},    
    {0, 0, 0, 0},
  };

  /* start parallel */
  mpp_init(&argc, &argv);
  mpp_domain_init();  

  /*
   * process command line
   */
  errflg = argc <3;

  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
    switch (c) {
    case 'a':
      strcpy(grid_type, optarg);
      break;
    case 'b':
      strcpy(entry, optarg);
      tokenize(entry, ",", STRINGLEN, MAXBOUNDS, my_grid_file, &ntiles_file);
      break;
    case 'c':
      nxbnds0 = atoi(optarg);
      break;
    case 'd':
      nybnds0 = atoi(optarg);
      break;        
    case 'e':
      strcpy(entry, optarg);
      nxbnds1 = get_double_entry(entry, xbnds);
      break;
    case 'f':
      strcpy(entry, optarg);
      nybnds1 = get_double_entry(entry, ybnds);
      break;
    case 'g':
      strcpy(entry, optarg);
      nxbnds2 = get_int_entry(entry, nlon);
      break;
    case 'i':
      strcpy(entry, optarg);
      nybnds2 = get_int_entry(entry, nlat);
      break;
    case 'j':
      lat_join = atof(optarg);
      break; 
    case 'k':
      nratio = atoi(optarg);
      break;      
    case 'l':
      simple_dx = atof(optarg);
      break;
    case 'm':
      simple_dy = atof(optarg);
      break;
    case 'o':
      strcpy(entry, optarg);
      ntilex = get_int_entry(entry, ndivx);
      break;
    case 'p':
      strcpy(entry, optarg);
      ntiley = get_int_entry(entry, ndivy);
      break;      
    case 'q':
      strcpy(gridname, optarg);
      break;
    case 'r':
      strcpy(center, optarg);
      break;
    case 'h':
      errflg++;
      break;
    case '?':
      errflg++;      
    }      
  }
  
  if (errflg ) {
    char **u = usage;
    while (*u) { fprintf(stderr, "%s\n", *u); u++; }
    exit(2);
  }  

  /* define history to be the history in the grid file */
  strcpy(history,argv[0]);

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

  if(mpp_pe() == mpp_root_pe() ) printf("==>NOTE: the grid type is %s\n",grid_type);


  /* check the command-line arguments to make sure the value are suitable */

  if( strcmp(grid_type,"regular_lonlat_grid") ==0 ) {
    nxbnds = nxbnds0; nybnds = nybnds0;
    if( nxbnds <2 || nybnds < 2) mpp_error("make_hgrid: grid type is 'regular_lonlat_grid', "
					   "both nxbnds and nybnds should be no less than 2");
    if( nxbnds != nxbnds1 || nxbnds != nxbnds2+1 )
      mpp_error("make_hgrid: grid type is 'regular_lonlat_grid', nxbnds does"
		"not match number of entry in xbnds or nlon");
    if( nybnds != nybnds1 || nybnds != nybnds2+1 )
      mpp_error("make_hgrid: grid type is 'regular_lonlat_grid', nybnds does "
		"not match number of entry in ybnds or nlat");
  }
  else if( strcmp(grid_type,"tripolar_grid") ==0 ) {
    strcpy(projection, "tripolar");
    nxbnds = nxbnds0; nybnds = nybnds0;
    if( nxbnds != 2) mpp_error("make_hgrid: grid type is 'tripolar_grid', nxbnds should be 2");
    if( nybnds < 2) mpp_error("make_hgrid: grid type is 'tripolar_grid', nybnds should be no less than 2");
    if( nxbnds != nxbnds1 || nxbnds != nxbnds2+1 )
      mpp_error("make_hgrid: grid type is 'tripolar_grid', nxbnds does not match number of entry in xbnds or nlon");
    if( nybnds != nybnds1 || nybnds != nybnds2+1 )
      mpp_error("make_hgrid: grid type is 'tripolar_grid', nybnds does not match number of entry in ybnds or nlat");
  }
  else if( strcmp(grid_type,"from_file") ==0 ) {
    /* For ascii file, nlon and nlat should be specified through --nlon, --nlat
       For netcdf file, grid resolution will be read from grid file
    */
    
    if(ntiles_file == 0) mpp_error("make_hgrid: grid_type is 'from_file', but my_grid_file is not specified");
    ntiles = ntiles_file;
    for(n=0; n<ntiles; n++) {
      if(strstr(my_grid_file[n],".nc") ) {
	/* get the grid size for each tile, the grid is on model grid, should need to multiply by 2 */
	int fid;
	fid = mpp_open(my_grid_file[n], MPP_READ);
	nlon[n] = mpp_get_dimlen(fid, "grid_xt")*2;
	nlat[n] = mpp_get_dimlen(fid, "grid_yt")*2;
	mpp_close(fid);
      }
      else {
	if(nxbnds2 != ntiles || nybnds2 != ntiles ) mpp_error("make_hgrid: grid type is 'from_file', number entry entered "
						"through --nlon and --nlat should be equal to number of files "
							  "specified through --my_grid_file");
      }
    }
    	/* for simplify purpose, currently we assume all the tile have the same grid size */
    for(n=1; n<ntiles; n++) {
      if( nlon[n] != nlon[0] || nlat[n] != nlat[0])  mpp_error("make_hgrid: grid_type is from_file, all the tiles should "
							       "have same grid size, contact developer");
    }
  }
  else if( strcmp(grid_type,"simple_cartesian_grid") ==0) {
    strcpy(geometry, "planar");
    strcpy(north_pole_tile, "none");
    if(nxbnds1 != 2 || nybnds1 != 2 ) mpp_error("make_hgrid: grid type is 'simple_cartesian_grid', number entry entered "
						"through --xbnds and --ybnds should be 2");
    if(nxbnds2 != 1 || nybnds2 != 1 ) mpp_error("make_hgrid: grid type is 'simple_cartesian_grid', number entry entered "
						"through --nlon and --nlat should be 1");
    if(simple_dx == 0 || simple_dy == 0) mpp_error("make_hgrid: grid_type is 'simple_cartesian_grid', "
						   "both simple_dx and simple_dy both should be specified");
  }
  else if ( strcmp(grid_type,"spectral_grid") ==0 ) {
    if(nxbnds2 != 1 || nybnds2 != 1 ) mpp_error("make_hgrid: grid type is 'spectral_grid', number entry entered "
						"through --nlon and --nlat should be 1");    
  }
  else if( strcmp(grid_type,"conformal_cubic_grid") ==0 ) {
    strcpy(projection, "cube_gnomonic");
    strcpy(conformal, "FALSE");
    if(nxbnds2 != 1 ) mpp_error("make_hgrid: grid type is 'conformal_cubic_grid', number entry entered "
				"through --nlon should be 1");
    if(nratio < 1) mpp_error("make_hgrid: grid type is 'conformal_cubic_grid', nratio should be a positive integer");
  }
  else if(  !strcmp(grid_type,"gnomonic_ed") ) {
    strcpy(projection, "cube_gnomonic");
    strcpy(conformal, "FALSE");
    if(nxbnds2 != 1 ) mpp_error("make_hgrid: grid type is 'gnomonic_cubic_grid', number entry entered "
				"through --nlon should be 1");
  }
  else {
    mpp_error("make_hgrid: only grid_type = 'regular_lonlat_grid', 'tripolar_grid', 'from_file', "
	      "'gnomonic_ed', 'conformal_cubic_grid', 'simple_cartesian_grid' and "
	      "'spectral_grid' is implemented");  
  }
  
  /* get super grid size */

  if( !strcmp(grid_type,"gnomonic_ed") || !strcmp(grid_type,"conformal_cubic_grid") ) {
    nx = nlon[0];
    ny = nx;
  }
  else {
    nx = 0;
    ny = 0;
    for(n=0; n<nxbnds-1; n++) nx += nlon[n];
    for(n=0; n<nybnds-1; n++) ny += nlat[n];  
  }
  nxp = nx + 1;
  nyp = ny + 1;

  if( !strcmp(grid_type,"gnomonic_ed") || !strcmp(grid_type,"conformal_cubic_grid") ) {
    ntiles = 6;
    /* Cubic grid is required to run on single processor.*/
    if(mpp_npes() > 1) mpp_error( "make_hgrid: cubic grid generation must be run one processor, contact developer");
  }
  /* Currently we restrict nx can be divided by ndivx and ny can be divided by ndivy */
  if(ntilex >0 && ntilex != ntiles) mpp_error("make_hgrid: number of entry specified through --ndivx does not equal ntiles");
  if(ntiley >0 && ntiley != ntiles) mpp_error("make_hgrid: number of entry specified through --ndivy does not equal ntiles");   
  for(n=0; n<ntiles; n++) {
    if( nx%ndivx[n] ) mpp_error("make_hgrid: nx can not be divided by ndivx");
    if( ny%ndivy[n] ) mpp_error("make_hgrid: ny can not be divided by ndivy");
  }

  if(strcmp(center,"none") && strcmp(center,"c_cell") && strcmp(center,"t_cell") )
    mpp_error("make_hgrid: center should be 'none', 'c_cell' or 't_cell' ");
  
  /* set up domain decomposition, x and y will be on global domain and
     other fields will be on compute domain. 
  */

  mpp_define_layout( nx, ny, mpp_npes(), layout);
  mpp_define_domain2d( nx, ny, layout, 0, 0, &domain);
  mpp_get_compute_domain2d(domain, &isc, &iec, &jsc, &jec);
  nxc = iec - isc + 1;
  nyc = jec - jsc + 1;

  /* create grid information */
  x        = (double *) malloc(nxp*nyp*ntiles*sizeof(double));
  y        = (double *) malloc(nxp*nyp*ntiles*sizeof(double));
  dx       = (double *) malloc(nxc*(nyc+1)*ntiles*sizeof(double));
  dy       = (double *) malloc((nxc+1)*nyc*ntiles*sizeof(double));
  area     = (double *) malloc(nxc    *nyc*ntiles*sizeof(double));
  angle_dx = (double *) malloc((nxc+1)*(nyc+1)*ntiles*sizeof(double));
  if( strcmp(conformal,"true") !=0 )angle_dy = (double *) malloc(nxp*nyp*ntiles*sizeof(double));
  
  if(strcmp(grid_type,"regular_lonlat_grid") ==0) 
    create_regular_lonlat_grid(&nxbnds, &nybnds, xbnds, ybnds, nlon, nlat, &isc, &iec, &jsc, &jec,
			       x, y, dx, dy, area, angle_dx, center);
  else if(strcmp(grid_type,"tripolar_grid") ==0) 
    create_tripolar_grid(&nxbnds, &nybnds, xbnds, ybnds, nlon, nlat, &lat_join, &isc, &iec, &jsc, &jec,
			 x, y, dx, dy, area, angle_dx, center);
  else if( strcmp(grid_type,"from_file") ==0 ) {
    for(n=0; n<ntiles; n++) {
      int n1, n2, n3, n4;
      n1 = n * nxp * nyp;
      n2 = n * nx  * nyp;
      n3 = n * nxp * ny;
      n4 = n * nx  * ny;
      create_grid_from_file(my_grid_file[n], &nx, &ny, x+n1, y+n1, dx+n2, dy+n3, area+n4, angle_dx+n1);
    }
  }
  else if(strcmp(grid_type,"simple_cartesian_grid") ==0) 
    create_simple_cartesian_grid(xbnds, ybnds, &nx, &ny, &simple_dx, &simple_dy, &isc, &iec, &jsc, &jec,
				 x, y, dx, dy, area, angle_dx );
  else if(strcmp(grid_type,"spectral_grid") ==0 )
    create_spectral_grid(&nx, &ny, &isc, &iec, &jsc, &jec, x, y, dx, dy, area, angle_dx );
  else if(strcmp(grid_type,"conformal_cubic_grid") ==0 ) 
    create_conformal_cubic_grid(&nx, &nratio, method, orientation, x, y, dx, dy, area, angle_dx, angle_dy );
  else if(strcmp(grid_type,"gnomonic_ed") ==0 ) 
    create_gnomonic_cubic_grid(grid_type, &nx, x, y, dx, dy, area, angle_dx, angle_dy );
  
  /* write out data */
  {
    int fid, id_tile, id_x, id_y, id_dx, id_dy, id_area, id_angle_dx, id_angle_dy, id_arcx;
    int dimlist[5], dims[2], i, j, l, ni, nj, nip, njp, m;
    size_t start[4], nwrite[4];
    double *tmp, *gdata;
    char tilename[128] = "";
    char outfile[128] = "";
    
    l = 0;
    for(n=0 ; n< ntiles; n++) {
      for(j=0; j<ndivy[n]; j++) {
	for(i=0; i<ndivx[n]; i++) {
	  ++l;
	  sprintf(tilename, "tile%d", l);
	  if(ntiles>1)
	    sprintf(outfile, "%s.tile%d.nc", gridname, l);
	  else
	    sprintf(outfile, "%s.nc", gridname);
	  fid = mpp_open(outfile, MPP_WRITE);
	  /* define dimenison */
	  ni = nx/ndivx[n];
	  nj = ny/ndivy[n];
	  nip = ni + 1;
	  njp = nj + 1;
	  dimlist[0] = mpp_def_dim(fid, "string", STRINGLEN);
	  dimlist[1] = mpp_def_dim(fid, "nx", ni);
	  dimlist[2] = mpp_def_dim(fid, "ny", nj);
	  dimlist[3] = mpp_def_dim(fid, "nxp", nip);
	  dimlist[4] = mpp_def_dim(fid, "nyp", njp);
	  /* define variable */
	  if( strcmp(north_pole_tile, "none") == 0) /* no north pole, then no projection */
	    id_tile = mpp_def_var(fid, "tile", MPP_CHAR, 1, dimlist, 4, "standard_name", "grid_tile_spec",
				  "geometry", geometry, "discretization", discretization, "conformal", conformal );
	  else if( strcmp(projection, "none") == 0) 
	    id_tile = mpp_def_var(fid, "tile", MPP_CHAR, 1, dimlist, 5, "standard_name", "grid_tile_spec",
				  "geometry", geometry, "north_pole", north_pole_tile, "discretization",
				  discretization, "conformal", conformal );
	  else
	    id_tile = mpp_def_var(fid, "tile", MPP_CHAR, 1, dimlist, 6, "standard_name", "grid_tile_spec",
				  "geometry", geometry, "north_pole", north_pole_tile, "projection", projection,
				  "discretization", discretization, "conformal", conformal );
	  dims[0] = dimlist[4]; dims[1] = dimlist[3];
	  id_x = mpp_def_var(fid, "x", MPP_DOUBLE, 2, dims, 2, "standard_name", "geographic_longitude",
			     "units", "degree_east");
	  id_y = mpp_def_var(fid, "y", MPP_DOUBLE, 2, dims, 2, "standard_name", "geographic_latitude",
			     "units", "degree_north");
	  dims[0] = dimlist[4]; dims[1] = dimlist[1];
	  id_dx = mpp_def_var(fid, "dx", MPP_DOUBLE, 2, dims, 2, "standard_name", "grid_edge_x_distance",
			      "units", "meters");
	  dims[0] = dimlist[2]; dims[1] = dimlist[3];
	  id_dy = mpp_def_var(fid, "dy", MPP_DOUBLE, 2, dims, 2, "standard_name", "grid_edge_y_distance",
			      "units", "meters");
	  dims[0] = dimlist[2]; dims[1] = dimlist[1];
	  id_area = mpp_def_var(fid, "area", MPP_DOUBLE, 2, dims, 2, "standard_name", "grid_cell_area",
				"units", "m2" );
	  dims[0] = dimlist[4]; dims[1] = dimlist[3];
	  id_angle_dx = mpp_def_var(fid, "angle_dx", MPP_DOUBLE, 2, dims, 2, "standard_name",
				    "grid_vertex_x_angle_WRT_geographic_east", "units", "degrees_east");
	  if(strcmp(conformal, "true") != 0)
	    id_angle_dy = mpp_def_var(fid, "angle_dy", MPP_DOUBLE, 2, dims, 2, "standard_name",
				      "grid_vertex_y_angle_WRT_geographic_north", "units", "degrees_north");
	  if( strcmp(north_pole_arcx, "none") == 0)
	    id_arcx = mpp_def_var(fid, "arcx", MPP_CHAR, 1, dimlist, 1, "standard_name", "grid_edge_x_arc_type" );
	  else
	    id_arcx = mpp_def_var(fid, "arcx", MPP_CHAR, 1, dimlist, 2, "standard_name", "grid_edge_x_arc_type",
				  "north_pole", north_pole_arcx );
	  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);
	  for(m=0; m<4; m++) { start[m] = 0; nwrite[m] = 0; }
	  nwrite[0] = strlen(tilename);
	  mpp_put_var_value_block(fid, id_tile, start, nwrite, tilename );

          tmp = get_subregion(nxp, x+n*nxp*nyp, i*ni, (i+1)*ni, j*nj, (j+1)*nj);
	  mpp_put_var_value(fid, id_x, tmp);
	  free(tmp);
          tmp = get_subregion(nxp, y+n*nxp*nyp, i*ni, (i+1)*ni, j*nj, (j+1)*nj);
	  mpp_put_var_value(fid, id_y, tmp);
	  free(tmp);
	  gdata = (double *)malloc(nx*nyp*sizeof(double));
	  mpp_global_field_double(domain, nxc, nyc+1, dx+n*nx*nyp, gdata);
	  tmp = get_subregion( nx, gdata, i*ni, (i+1)*ni-1, j*nj, (j+1)*nj);
	  mpp_put_var_value(fid, id_dx, tmp);
	  free(tmp);
	  free(gdata);
	  gdata = (double *)malloc(nxp*ny*sizeof(double));
	  mpp_global_field_double(domain, nxc+1, nyc, dy+n*nxp*ny, gdata);
	  tmp = get_subregion( nxp, gdata, i*ni, (i+1)*ni, j*nj, (j+1)*nj-1);
	  mpp_put_var_value(fid, id_dy, tmp);
	  free(tmp);
	  free(gdata);	  
	  gdata = (double *)malloc(nx*ny*sizeof(double));
	  mpp_global_field_double(domain, nxc, nyc, area+n*nx*ny, gdata);
	  tmp = get_subregion( nx, gdata, i*ni, (i+1)*ni-1, j*nj, (j+1)*nj-1);
	  mpp_put_var_value(fid, id_area, tmp);
	  free(tmp);
	  free(gdata);
	  gdata = (double *)malloc(nxp*nyp*sizeof(double));
	  mpp_global_field_double(domain, nxc+1, nyc+1, angle_dx+n*nxp*nyp, gdata);
	  tmp = get_subregion( nxp, gdata, i*ni, (i+1)*ni, j*nj, (j+1)*nj);
	  mpp_put_var_value(fid, id_angle_dx, tmp);
	  free(tmp);
	  free(gdata);
	  
	  if(strcmp(conformal, "true") != 0) {
	    gdata = (double *)malloc(nxp*nyp*sizeof(double));
	    mpp_global_field_double(domain, nxc+1, nyc+1, angle_dy+n*nxp*nyp, gdata);
	    tmp = get_subregion( nxp, gdata, i*ni, (i+1)*ni, j*nj, (j+1)*nj);
	    mpp_put_var_value(fid, id_angle_dy, tmp);
	    free(tmp);
	    free(gdata);
	  }
	  nwrite[0] = strlen(arcx);
	  mpp_put_var_value_block(fid, id_arcx, start, nwrite, arcx );
	  mpp_close(fid);
	}
      }
    }
  }

  free(x);
  free(y);
  free(dx);
  free(dy);
  free(area);
  free(angle_dx);
  if(strcmp(conformal, "true") != 0) free(angle_dy);
  if(mpp_pe() == mpp_root_pe()) printf("generate_grid is run successfully. \n");

  mpp_end();

  return 0;
  
};  /* end of main */
Beispiel #14
0
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 *ocean_topog = NULL;
  double sea_level = 0.;
  char mosaic_name[STRING] = "mosaic", mosaic_file[STRING];
  char griddir[STRING], solo_mosaic[STRING], filepath[STRING];
  char history[512];
  int  use_ocean_topog = 0;  

  static struct option long_options[] = {
    {"input_mosaic",       required_argument, NULL, 'i'},
    {"mosaic_name",        required_argument, NULL, 'm'},
    {"sea_level",          required_argument, NULL, 's'},
    {"ocean_topog",        required_argument, NULL, 'o'},
    {NULL, 0, NULL, 0}
  };

  
  /*
   * process command line
   */

  while ((c = getopt_long(argc, argv, "i:m:o:", long_options, &option_index) ) != -1)
    switch (c) {
    case 'i': 
      input_mosaic = optarg;
      break;
    case 'm':
      strcpy(mosaic_name,optarg);
      break;
    case 's':
      sea_level = atof(optarg);
      break;
    case 'o':
      ocean_topog = 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]);
  }

  /*When ocean_topog specified, input_mosaic is a solo mosaic and will use ocean_topog,
    when ocean_topog is not specified, input_mosaic is a coupled mosaic will use land/sea mask
    for the land grid in the input_mosaic.
  */

  if( ocean_topog ) {
    use_ocean_topog = 1;
    if( ! mpp_field_exist(input_mosaic, "gridfiles") ) {
      mpp_error("make_quick_mosaic: field gridfiles does not exist in input_mosaic");
    }
  }
  else {/* check to make sure it is coupled mosaic */
    use_ocean_topog = 0;
    if( ! mpp_field_exist(input_mosaic, "lnd_mosaic_file") ) {
      mpp_error("make_quick_mosaic: field lnd_mosaic_file does not exist in input_mosaic");
    }
  }
  /* First get land grid information */
  
  mpp_init(&argc, &argv);
  sprintf(mosaic_file, "%s.nc", mosaic_name);
  get_file_path(input_mosaic, griddir);
  if( use_ocean_topog ) {
    get_file_name( input_mosaic, solo_mosaic);
  }
  else {
    fid = mpp_open(input_mosaic, MPP_READ);
    vid = mpp_get_varid(fid, "lnd_mosaic_file");
    mpp_get_var_value(fid, vid, solo_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, solo_mosaic);
  }

  sprintf(filepath, "%s/%s", griddir, solo_mosaic);
  ntiles = read_mosaic_ntiles(filepath);
  if(use_ocean_topog ) nfile_aXl = ntiles;
  /* copy the solo_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, solo_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);
     }
  }


  /* get grid cell area */
  cell_area = (double **)malloc(ntiles*sizeof(double *));
  land_area = (double **)malloc(ntiles*sizeof(double *));
  ocean_area = (double **)malloc(ntiles*sizeof(double *));
  for(n=0; n<ntiles; n++) {
    land_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double));
    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]);
  }

  /* get the ocean and land area. */
  if( use_ocean_topog ) {
    int t_fid, t_vid, ntiles2, nlon, nlat;
    /* first read ocean topography */
    t_fid = mpp_open(ocean_topog, MPP_READ);
    ntiles2 = mpp_get_dimlen(t_fid, "ntiles");
    if(ntiles2 != ntiles) mpp_error("make_quick_mosaic: dimlen ntiles in mosaic file is not the same as dimlen in topog file");
    for(n=0; n<ntiles; n++) {
      char name[128];
      char depth_name[128], mask_name[128];
      int i, j;
      double *depth, *omask;
      int mask_name_exist;
      
      if(ntiles == 1)
	strcpy(name, "nx");
      else
	sprintf(name, "nx_tile%d", n+1);
      nlon = mpp_get_dimlen(t_fid, name);
      if(ntiles == 1)
	strcpy(name, "ny");
      else
	sprintf(name, "ny_tile%d", n+1);
      nlat = mpp_get_dimlen(t_fid, name);
      if( nlon != nx[n] || nlat != ny[n]) mpp_error("make_quick_mosaic: grid size mismatch between mosaic file and topog file");
      if(ntiles == 1) {
	strcpy(depth_name, "depth");
	strcpy(mask_name, "area_frac");
      }
      else {
	sprintf(depth_name, "depth_tile%d", n+1);
        sprintf(mask_name, "area_frac_tile%d", n+1);
      }      
      omask = (double *)malloc(nx[n]*ny[n]*sizeof(double));
      for(i=0; i<nx[n]*ny[n]; i++) omask[i] = 0;
      mask_name_exist = mpp_var_exist(t_fid, mask_name);

      if(mask_name_exist) {
	if(mpp_pe() == mpp_root_pe() ) printf("\nNOTE from make_quick_mosaic: the ocean land/sea mask will be "
					     "determined by field area_frac from file %s\n", ocean_topog);
	t_vid = mpp_get_varid(t_fid, mask_name);
	mpp_get_var_value(t_fid, t_vid, omask);
      }
      else {
	if(mpp_pe() == mpp_root_pe()) printf("\nNOTE from make_coupler_mosaic: the ocean land/sea mask will be "
					     "determined by field depth from file %s\n", ocean_topog);
	t_vid = mpp_get_varid(t_fid, depth_name);
	depth    = (double *)malloc(nx[n]*ny[n]*sizeof(double));
        mpp_get_var_value(t_fid, t_vid, depth);
	for(i=0; i<nx[n]*ny[n]; i++) {
	  if(depth[i] >sea_level) omask[i] = 1;
	}
	free(depth);
      }
      /* Now calculate the ocean and land grid cell area. */
      for(i=0; i<nx[n]*ny[n]; i++) {
	if(omask[i] == 1) {
	  land_area[n][i] = 0;
	  ocean_area[n][i] = cell_area[n][i];
	}
	else {
	  ocean_area[n][i] = 0;
	  land_area[n][i] = cell_area[n][i];
	}
      }
      free(omask);
    }
    mpp_close(t_fid);
  }            
  else {
  
    /* read the exchange grid information and get the land/sea mask of land model*/
    for(n=0; n<ntiles; n++) {
      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 */
    for(n=0; n<ntiles; 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(solo_mosaic);
    mpp_put_var_value_block(fid, id_lmosaic_file, start, nwrite, solo_mosaic);
    mpp_put_var_value_block(fid, id_amosaic_file, start, nwrite, solo_mosaic);
    mpp_put_var_value_block(fid, id_omosaic_file, start, nwrite, solo_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 */