void get_grid_v1(int fid, double *xt, double *yt, double *xc, double *yc) { int vid; vid = mpp_get_varid(fid, "grid_lon"); mpp_get_var_value(fid, vid, xc); vid = mpp_get_varid(fid, "grid_lat"); mpp_get_var_value(fid, vid, yc); vid = mpp_get_varid(fid, "grid_lont"); mpp_get_var_value(fid, vid, xt); vid = mpp_get_varid(fid, "grid_latt"); mpp_get_var_value(fid, vid, yt); }
void get_grid_v3(int fid, int nlon, int nlat, double *xt, double *yt, double *xc, double *yc) { int vid, i, j; double *lon=NULL, *lat=NULL; double *lon_bnds=NULL, *lat_bnds=NULL; lon = (double *)malloc(nlon*sizeof(double)); lat = (double *)malloc(nlat*sizeof(double)); lon_bnds = (double *)malloc(2*nlon*sizeof(double)); lat_bnds = (double *)malloc(2*nlat*sizeof(double)); vid = mpp_get_varid(fid, "lon"); mpp_get_var_value(fid, vid, lon); vid = mpp_get_varid(fid, "lat"); mpp_get_var_value(fid, vid, lat); vid = mpp_get_varid(fid, "lon_bnds"); mpp_get_var_value(fid, vid, lon_bnds); vid = mpp_get_varid(fid, "lat_bnds"); mpp_get_var_value(fid, vid, lat_bnds); for(j=0; j<nlat; j++) for(i=0; i<nlon; i++) { xt[j*nlon+i] = lon[i]; yt[j*nlon+i] = lat[j]; } for(j=0; j<nlat+1; j++) { for(i=0; i<nlon; i++) { xc[j*(nlon+1)+i] = lon_bnds[2*i]; } xc[j*(nlon+1)+nlon] = lon_bnds[2*nlon-1]; } for(i=0; i<nlon+1; i++) { for(j=0; j<nlat; j++) { yc[j*(nlon+1)+i] = lat_bnds[2*j]; } yc[nlat*(nlon+1)+i] = lat_bnds[2*nlat-1]; } free(lon); free(lat); free(lon_bnds); free(lat_bnds); }
void get_grid_v2(int fid, int nlon, int nlat, double *xt, double *yt, double *xc, double *yc) { int vid, i, j; double *x_vert=NULL, *y_vert=NULL; vid = mpp_get_varid(fid, "lon"); mpp_get_var_value(fid, vid, xt); vid = mpp_get_varid(fid, "lat"); mpp_get_var_value(fid, vid, yt); x_vert = (double *)malloc(nlon*nlat*4*sizeof(double)); y_vert = (double *)malloc(nlon*nlat*4*sizeof(double)); vid = mpp_get_varid(fid, "lon_vertices"); mpp_get_var_value(fid, vid, x_vert); vid = mpp_get_varid(fid, "lat_vertices"); mpp_get_var_value(fid, vid, y_vert); for(j=0; j<nlat; j++) for(i=0; i<nlon; i++) { xc[j*(nlon+1)+i] = x_vert[(j*nlon+i)*4]; yc[j*(nlon+1)+i] = y_vert[(j*nlon+i)*4]; } for(j=0; j<nlat; j++) { xc[j*(nlon+1)+nlon] = x_vert[(j*nlon+nlon-1)*4+1]; yc[j*(nlon+1)+nlon] = y_vert[(j*nlon+nlon-1)*4+1]; } for(i=0; i<nlon; i++) { xc[nlat*(nlon+1)+i] = x_vert[((nlat-1)*nlon+i)*4+3]; yc[nlat*(nlon+1)+i] = y_vert[((nlat-1)*nlon+i)*4+3]; } xc[nlat*(nlon+1)+nlon] = x_vert[(nlat*nlon-1)*4+2]; yc[nlat*(nlon+1)+nlon] = y_vert[(nlat*nlon-1)*4+2]; free(x_vert); free(y_vert); }
main (int argc, char *argv[]) { extern char *optarg; char *pch=NULL, *dir=NULL, history[512], entry[1280]; char tilefile[MAXTILE][STRING], tiletype[MAXTILE][SHORTSTRING]; char tile_name[MAXTILE][STRING]; int ntiles=0, nfiles=0, ncontact=0; int *nxp, *nyp; double **x, **y; double periodx=0, periody=0; int contact_tile1[MAXCONTACT], contact_tile2[MAXCONTACT]; int contact_tile1_istart[MAXCONTACT], contact_tile1_iend[MAXCONTACT]; int contact_tile1_jstart[MAXCONTACT], contact_tile1_jend[MAXCONTACT]; int contact_tile2_istart[MAXCONTACT], contact_tile2_iend[MAXCONTACT]; int contact_tile2_jstart[MAXCONTACT], contact_tile2_jend[MAXCONTACT]; char mosaic_name[128] = "solo_mosaic"; char grid_descriptor[128] = ""; int c, i, n, m, l, errflg; int option_index = 0; static struct option long_options[] = { {"mosaic_name", required_argument, NULL, 'm'}, {"num_tiles", required_argument, NULL, 'n'}, {"grid_descriptor", required_argument, NULL, 'g'}, {"tile_file", required_argument, NULL, 'f'}, {"periodx", required_argument, NULL, 'x'}, {"periody", required_argument, NULL, 'y'}, {"directory", required_argument, NULL, 'd'}, {NULL, 0, NULL, 0} }; mpp_init(&argc, &argv); /* this tool must be run one processor */ if(mpp_npes()>1) mpp_error("make_solo_mosaic: this tool must be run on one processor"); errflg = (argc == 1); /* First read command line arguments. */ while ((c = getopt_long(argc, argv, "h", long_options, &option_index)) != -1) { switch (c) { case 'n': ntiles = atoi(optarg); break; case 'm': strcpy(mosaic_name, optarg); break; case 'g': strcpy(grid_descriptor, optarg); break; case 'f': strcpy(entry, optarg); pch = strtok(entry, ", "); nfiles = 0; while( pch != NULL) { strcpy(tilefile[nfiles++], pch); pch = strtok(NULL, ", "); } break; case 'x': periodx = atof(optarg); break; case 'y': periody = atof(optarg); break; case 'd': // path of the simple grid file. dir = optarg; break; case '?': errflg++; } } if (errflg || ntiles < 1 || !dir ) { char **u = usage; while (*u) { fprintf(stderr, "%s\n", *u); u++; } exit(2); } strcpy(history,argv[0]); for(i=1;i<argc;i++) { strcat(history, " "); strcat(history, argv[i]); } if(ntiles > MAXTILE) { mpp_error("make_solo_mosaic: number of tiles is greater than MAXTILE."); } /*--- if file name is not specified through -f, file name will be horizontal_grid.tile#.nc */ if(nfiles == 0) { if(ntiles == 1) { sprintf(tilefile[0],"horizontal_grid.nc"); } else { for(n=0; n<ntiles; n++) { sprintf(tilefile[n],"horizontal_grid.tile%d.nc",n+1); } } } else { /* Check if ntile are matching number of grid file passed through -f */ if( nfiles != ntiles) mpp_error("make_solo_mosaic: number of grid files specified through -n " " does not equal to number of files specified through -f = "); } n = strlen(dir); if( dir[n-1] != '/') strcat(dir, "/"); /*First read all the grid files.*/ nxp = (int *)malloc(ntiles*sizeof(int)); nyp = (int *)malloc(ntiles*sizeof(int)); x = (double **)malloc(ntiles*sizeof(double *)); y = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { char filepath[512]; int fid, vid; sprintf(filepath, "%s%s",dir, tilefile[n]); fid = mpp_open(filepath, MPP_READ); nxp[n] = mpp_get_dimlen(fid, "nxp"); nyp[n] = mpp_get_dimlen(fid, "nyp"); x[n] = (double *)malloc(nxp[n]*nyp[n]*sizeof(double)); y[n] = (double *)malloc(nxp[n]*nyp[n]*sizeof(double)); vid = mpp_get_varid(fid, "tile"); mpp_get_var_value(fid, vid, tile_name[n]); vid = mpp_get_varid(fid, "x"); mpp_get_var_value(fid, vid, x[n]); vid = mpp_get_varid(fid, "y"); mpp_get_var_value(fid, vid, y[n]); mpp_close(fid); } /*find the contact region between tiles, currently assume the contact region are align-contact There should be no contact between same directions of two tiles ( w-w, e-e, s-s, n-n) We assume no contact between w-s, e-n ( will added in if needed ) . */ ncontact = 0; for(n=0; n<ntiles; n++) { for(m=n; m<ntiles; m++) { int count; int istart1[MAXCONTACT], iend1[MAXCONTACT], jstart1[MAXCONTACT], jend1[MAXCONTACT]; int istart2[MAXCONTACT], iend2[MAXCONTACT], jstart2[MAXCONTACT], jend2[MAXCONTACT]; count = get_align_contact(n+1, m+1, nxp[n], nyp[n], nxp[m], nyp[m], x[n], y[n], x[m], y[m], periodx, periody, istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2); if(ncontact+count>MAXCONTACT) mpp_error("make_solo_mosaic: number of contacts is more than MAXCONTACT 1"); for(l=0; l<count; l++) { contact_tile1_istart[ncontact] = istart1[l]; contact_tile1_iend [ncontact] = iend1[l]; contact_tile1_jstart[ncontact] = jstart1[l]; contact_tile1_jend [ncontact] = jend1[l]; contact_tile2_istart[ncontact] = istart2[l]; contact_tile2_iend [ncontact] = iend2[l]; contact_tile2_jstart[ncontact] = jstart2[l]; contact_tile2_jend [ncontact] = jend2[l]; contact_tile1 [ncontact] = n; contact_tile2 [ncontact] = m; ncontact++; } } } for(n=0; n<ntiles; n++) { for(m=n+1; m<ntiles; m++) { int count; int istart1[MAXCONTACT], iend1[MAXCONTACT], jstart1[MAXCONTACT], jend1[MAXCONTACT]; int istart2[MAXCONTACT], iend2[MAXCONTACT], jstart2[MAXCONTACT], jend2[MAXCONTACT]; count = get_overlap_contact(n+1, m+1, nxp[n], nyp[n], nxp[m], nyp[m], x[n], y[n], x[m], y[m], istart1, iend1, jstart1, jend1, istart2, iend2, jstart2, jend2); if(ncontact+count>MAXCONTACT) mpp_error("make_solo_mosaic: number of contacts is more than MAXCONTACT 2"); for(l=0; l<count; l++) { contact_tile1_istart[ncontact] = istart1[l]; contact_tile1_iend [ncontact] = iend1[l]; contact_tile1_jstart[ncontact] = jstart1[l]; contact_tile1_jend [ncontact] = jend1[l]; contact_tile2_istart[ncontact] = istart2[l]; contact_tile2_iend [ncontact] = iend2[l]; contact_tile2_jstart[ncontact] = jstart2[l]; contact_tile2_jend [ncontact] = jend2[l]; contact_tile1 [ncontact] = n; contact_tile2 [ncontact] = m; ncontact++; } } } /* write out data */ { char str[STRING], outfile[STRING]; int fid, dim_ntiles, dim_ncontact, dim_string, id_mosaic, id_gridtiles, id_contacts; int id_contact_index, id_griddir, id_gridfiles, dim[2]; size_t start[4], nwrite[4]; sprintf(outfile, "%s.nc", mosaic_name); fid = mpp_open(outfile, MPP_WRITE); /* define dimenison */ dim_ntiles = mpp_def_dim(fid, "ntiles", ntiles); if(ncontact>0) dim_ncontact = mpp_def_dim(fid, "ncontact", ncontact); dim_string = mpp_def_dim(fid, "string", STRING); /* define variable */ id_mosaic = mpp_def_var(fid, "mosaic", MPP_CHAR, 1, &dim_string, 4, "standard_name", "grid_mosaic_spec", "children", "gridtiles", "contact_regions", "contacts", "grid_descriptor", grid_descriptor); dim[0] = dim_ntiles; dim[1] = dim_string; id_griddir = mpp_def_var(fid, "gridlocation", MPP_CHAR, 1, &dim[1], 1, "standard_name", "grid_file_location"); id_gridfiles = mpp_def_var(fid, "gridfiles", MPP_CHAR, 2, dim, 0); id_gridtiles = mpp_def_var(fid, "gridtiles", MPP_CHAR, 2, dim, 0); if(ncontact>0) { dim[0] = dim_ncontact; dim[1] = dim_string; id_contacts = mpp_def_var(fid, "contacts", MPP_CHAR, 2, dim, 5, "standard_name", "grid_contact_spec", "contact_type", "boundary", "alignment", "true", "contact_index", "contact_index", "orientation", "orient"); id_contact_index = mpp_def_var(fid, "contact_index", MPP_CHAR, 2, dim, 1, "standard_name", "starting_ending_point_index_of_contact"); } mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); mpp_end_def(fid); /* write out data */ for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } nwrite[0] = strlen(mosaic_name); mpp_put_var_value_block(fid, id_mosaic, start, nwrite, mosaic_name); nwrite[0] = strlen(dir); mpp_put_var_value_block(fid, id_griddir, start, nwrite, dir); nwrite[0] = 1; for(n=0; n<ntiles; n++) { start[0] = n; nwrite[1] = strlen(tile_name[n]); mpp_put_var_value_block(fid, id_gridtiles, start, nwrite, tile_name[n]); nwrite[1] = strlen(tilefile[n]); mpp_put_var_value_block(fid, id_gridfiles, start, nwrite, tilefile[n]); } for(n=0; n<ncontact; n++) { sprintf(str,"%s:%s::%s:%s", mosaic_name, tile_name[contact_tile1[n]], mosaic_name, tile_name[contact_tile2[n]]); start[0] = n; nwrite[1] = strlen(str); mpp_put_var_value_block(fid, id_contacts, start, nwrite, str); sprintf(str,"%d:%d,%d:%d::%d:%d,%d:%d", contact_tile1_istart[n], contact_tile1_iend[n], contact_tile1_jstart[n], contact_tile1_jend[n], contact_tile2_istart[n], contact_tile2_iend[n], contact_tile2_jstart[n], contact_tile2_jend[n] ); nwrite[1] = strlen(str); mpp_put_var_value_block(fid, id_contact_index, start, nwrite, str); } mpp_close(fid); } printf("congradulation: You have successfully run make_solo_mosaic\n"); return 0; }; // end of main
int main (int argc, char *argv[]) { int c, n, i; int errflg = (argc == 1); int option_index = 0; int fid, vid, nfile_aXl, ntiles; int *nx, *ny; double **lonb, **latb, **land_area, **ocean_area, **cell_area; char **axl_file = NULL, **axo_file=NULL, **lxo_file=NULL; char **ocn_topog_file = NULL; char *input_mosaic = NULL; char mosaic_name[STRING] = "mosaic", mosaic_file[STRING]; char griddir[STRING], lnd_mosaic[STRING], filepath[STRING]; char history[512]; static struct option long_options[] = { {"input_mosaic", required_argument, NULL, 'i'}, {"mosaic_name", required_argument, NULL, 'm'}, {NULL, 0, NULL, 0} }; /* * process command line */ while ((c = getopt_long(argc, argv, "i:", long_options, &option_index) ) != -1) switch (c) { case 'i': input_mosaic = optarg; break; case 'm': strcpy(mosaic_name,optarg); break; case '?': errflg++; } if (errflg || !input_mosaic) { char **u = usage; while (*u) { fprintf(stderr, "%s\n", *u); u++; } exit(2); } strcpy(history,argv[0]); for(i=1;i<argc;i++) { strcat(history, " "); strcat(history, argv[i]); } /* First get land grid information */ mpp_init(&argc, &argv); sprintf(mosaic_file, "%s.nc", mosaic_name); get_file_path(input_mosaic, griddir); fid = mpp_open(input_mosaic, MPP_READ); vid = mpp_get_varid(fid, "lnd_mosaic_file"); mpp_get_var_value(fid, vid, lnd_mosaic); nfile_aXl = mpp_get_dimlen( fid, "nfile_aXl"); /*make sure the directory that stores the mosaic_file is not current directory */ { char cur_path[STRING]; if(getcwd(cur_path, STRING) != cur_path ) mpp_error("make_quick_mosaic: The size of cur_path maybe is not big enough"); printf("The current directory is %s\n", cur_path); printf("The mosaic file location is %s\n", griddir); if(strcmp(griddir, cur_path)==0 || strcmp( griddir, ".")==0) mpp_error("make_quick_mosaic: The input mosaic file location should not be current directory"); } sprintf(filepath, "%s/%s", griddir, lnd_mosaic); ntiles = read_mosaic_ntiles(filepath); /* copy the lnd_mosaic file and grid file */ { int fid2, vid2; char cmd[STRING], gridfile[STRING]; size_t start[4], nread[4]; sprintf(cmd, "cp %s %s", filepath, lnd_mosaic); system(cmd); fid2 = mpp_open(filepath, MPP_READ); vid2 = mpp_get_varid(fid2, "gridfiles"); for(i=0; i<4; i++) { start[i] = 0; nread[i] = 1; } for(n=0; n<ntiles; n++) { start[0] = n; nread[1] = STRING; mpp_get_var_value_block(fid2, vid2, start, nread, gridfile); sprintf(cmd, "cp %s/%s %s", griddir, gridfile, gridfile); printf("%s \n", cmd); system(cmd); } mpp_close(fid2); } /* ntiles should be either 1 or ntiles = nfile_aXl */ if(ntiles != nfile_aXl && ntiles != 1) mpp_error("make_quick_mosaic: only support ntiles = 1 or ntiles = nfile_aXl, contact developer"); nx = (int *)malloc(ntiles*sizeof(int)); ny = (int *)malloc(ntiles*sizeof(int)); read_mosaic_grid_sizes(filepath, nx, ny); lonb = (double **)malloc(ntiles*sizeof(double *)); latb = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { lonb[n] = (double *)malloc((nx[n]+1)*(ny[n]+1)*sizeof(double)); latb[n] = (double *)malloc((nx[n]+1)*(ny[n]+1)*sizeof(double)); read_mosaic_grid_data(filepath, "x", nx[n], ny[n], lonb[n], n, 0, 0); read_mosaic_grid_data(filepath, "y", nx[n], ny[n], latb[n], n, 0, 0); for(i=0; i<(nx[n]+1)*(ny[n]+1); i++) { lonb[n][i] *= (M_PI/180.0); latb[n][i] *= (M_PI/180.0); } } /* read the exchange grid information and get the land/sea mask of land model*/ land_area = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { land_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double)); for(i=0; i<nx[n]*ny[n]; i++) land_area[n][i] = 0; } vid = mpp_get_varid(fid, "aXl_file"); for(n=0; n<nfile_aXl; n++) { size_t start[4], nread[4]; int nxgrid; char aXl_file[STRING]; start[0] = n; start[1] = 0; nread[0] = 1; nread[1] = STRING; mpp_get_var_value_block(fid, vid, start, nread, aXl_file); sprintf(filepath, "%s/%s", griddir, aXl_file); nxgrid = read_mosaic_xgrid_size(filepath); if(nxgrid>0) { int l; int *i1, *j1, *i2, *j2; double *area; i1 = (int *)malloc(nxgrid*sizeof(int)); j1 = (int *)malloc(nxgrid*sizeof(int)); i2 = (int *)malloc(nxgrid*sizeof(int)); j2 = (int *)malloc(nxgrid*sizeof(int)); area = (double *)malloc(nxgrid*sizeof(double)); read_mosaic_xgrid_order1(filepath, i1, j1, i2, j2, area); if(ntiles == 1) { for(l=0; l<nxgrid; l++) land_area[0][j2[l]*nx[0]+i2[l]] += (area[l]*4*M_PI*RADIUS*RADIUS); } else { for(l=0; l<nxgrid; l++) land_area[n][j2[l]*nx[n]+i2[l]] += (area[l]*4*M_PI*RADIUS*RADIUS); } free(i1); free(j1); free(i2); free(j2); free(area); } } mpp_close(fid); /* calculate ocean area */ ocean_area = (double **)malloc(ntiles*sizeof(double *)); cell_area = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { ocean_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double)); cell_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double)); get_grid_area(&nx[n], &ny[n], lonb[n], latb[n], cell_area[n]); for(i=0; i<nx[n]*ny[n]; i++) { ocean_area[n][i] = cell_area[n][i]; if( fabs(ocean_area[n][i]-land_area[n][i])/ocean_area[n][i] < AREA_RATIO_THRESH ) ocean_area[n][i] = 0; else ocean_area[n][i] -= land_area[n][i]; if(ocean_area[n][i] < 0) { printf("at i = %d, ocean_area = %g, land_area = %g, cell_area=%g\n", i, ocean_area[n][i], land_area[n][i], cell_area[n][i]); mpp_error("make_quick_mosaic: ocean area is negative at some points"); } } } /* write out land mask */ { for(n=0; n<ntiles; n++) { int fid, id_mask, dims[2]; char lnd_mask_file[STRING]; double *mask; mask = (double *)malloc(nx[n]*ny[n]*sizeof(double)); for(i=0; i<nx[n]*ny[n]; i++) mask[i] = land_area[n][i]/cell_area[n][i]; if(ntiles > 1) sprintf(lnd_mask_file, "land_mask_tile%d.nc", n+1); else strcpy(lnd_mask_file, "land_mask.nc"); fid = mpp_open(lnd_mask_file, MPP_WRITE); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dims[1] = mpp_def_dim(fid, "nx", nx[n]); dims[0] = mpp_def_dim(fid, "ny", ny[n]); id_mask = mpp_def_var(fid, "mask", MPP_DOUBLE, 2, dims, 2, "standard_name", "land fraction at T-cell centers", "units", "none"); mpp_end_def(fid); mpp_put_var_value(fid, id_mask, mask); free(mask); mpp_close(fid); } } /* write out ocean mask */ { for(n=0; n<ntiles; n++) { int fid, id_mask, dims[2]; char ocn_mask_file[STRING]; double *mask; mask = (double *)malloc(nx[n]*ny[n]*sizeof(double)); for(i=0; i<nx[n]*ny[n]; i++) mask[i] = ocean_area[n][i]/cell_area[n][i]; if(ntiles > 1) sprintf(ocn_mask_file, "ocean_mask_tile%d.nc", n+1); else strcpy(ocn_mask_file, "ocean_mask.nc"); fid = mpp_open(ocn_mask_file, MPP_WRITE); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dims[1] = mpp_def_dim(fid, "nx", nx[n]); dims[0] = mpp_def_dim(fid, "ny", ny[n]); id_mask = mpp_def_var(fid, "mask", MPP_DOUBLE, 2, dims, 2, "standard_name", "ocean fraction at T-cell centers", "units", "none"); mpp_end_def(fid); mpp_put_var_value(fid, id_mask, mask); free(mask); mpp_close(fid); } } ocn_topog_file = (char **)malloc(ntiles*sizeof(char *)); axl_file = (char **)malloc(ntiles*sizeof(char *)); axo_file = (char **)malloc(ntiles*sizeof(char *)); lxo_file = (char **)malloc(ntiles*sizeof(char *)); for(n=0; n<ntiles; n++) { axl_file[n] = (char *)malloc(STRING*sizeof(char)); axo_file[n] = (char *)malloc(STRING*sizeof(char)); lxo_file[n] = (char *)malloc(STRING*sizeof(char)); ocn_topog_file[n] = (char *)malloc(STRING*sizeof(char)); sprintf(ocn_topog_file[n], "ocean_topog_tile%d.nc", n+1); sprintf(axl_file[n], "atmos_mosaic_tile%dXland_mosaic_tile%d.nc", n+1, n+1); sprintf(axo_file[n], "atmos_mosaic_tile%dXocean_mosaic_tile%d.nc", n+1, n+1); sprintf(lxo_file[n], "land_mosaic_tile%dXocean_mosaic_tile%d.nc", n+1, n+1); } for(n=0; n<ntiles; n++) { int *i1, *j1, *i2, *j2; double *area, *di, *dj; int nxgrid, i, j; int fid, dim_string, dim_ncells, dim_two, dims[2]; int id_contact, id_tile1_cell, id_tile2_cell; int id_xgrid_area, id_tile1_dist, id_tile2_dist; size_t start[4], nwrite[4]; char contact[STRING]; for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } /* first calculate the atmXlnd exchange grid */ i1 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); j1 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); i2 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); j2 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); area = (double *)malloc(nx[n]*ny[n]*sizeof(double)); di = (double *)malloc(nx[n]*ny[n]*sizeof(double)); dj = (double *)malloc(nx[n]*ny[n]*sizeof(double)); /* write out the atmosXland exchange grid file, The file name will be atmos_mosaic_tile#Xland_mosaic_tile#.nc */ nxgrid = 0; for(j=0; j<ny[n]; j++) for(i=0; i<nx[n]; i++) { if(land_area[n][j*nx[n]+i] >0) { i1[nxgrid] = i+1; j1[nxgrid] = j+1; i2[nxgrid] = i+1; j2[nxgrid] = j+1; area[nxgrid] = land_area[n][j*nx[n]+i]; di[nxgrid] = 0; dj[nxgrid] = 0; nxgrid++; } } fid = mpp_open(axl_file[n], MPP_WRITE); sprintf(contact, "atmos_mosaic:tile%d::land_mosaic:tile%d", n+1, n+1); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec", "contact_type", "exchange", "parent1_cell", "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance"); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid"); mpp_end_def(fid); nwrite[0] = strlen(contact); mpp_put_var_value_block(fid, id_contact, start, nwrite, contact); nwrite[0] = nxgrid; mpp_put_var_value(fid, id_xgrid_area, area); mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di); start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj); mpp_close(fid); /* write out the atmosXocean exchange grid file, The file name will be atmos_mosaic_tile#Xocean_mosaic_tile#.nc */ nxgrid = 0; for(j=0; j<ny[n]; j++) for(i=0; i<nx[n]; i++) { if(ocean_area[n][j*nx[n]+i] >0) { i1[nxgrid] = i+1; j1[nxgrid] = j+1; i2[nxgrid] = i+1; j2[nxgrid] = j+1; area[nxgrid] = ocean_area[n][j*nx[n]+i]; di[nxgrid] = 0; dj[nxgrid] = 0; nxgrid++; } } fid = mpp_open(axo_file[n], MPP_WRITE); sprintf(contact, "atmos_mosaic:tile%d::ocean_mosaic:tile%d", n+1, n+1); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec", "contact_type", "exchange", "parent1_cell", "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance"); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid"); mpp_end_def(fid); start[1] = 0; nwrite[0] = strlen(contact); mpp_put_var_value_block(fid, id_contact, start, nwrite, contact); nwrite[0] = nxgrid; mpp_put_var_value(fid, id_xgrid_area, area); mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di); start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj); mpp_close(fid); /* write out landXocean exchange grid information */ fid = mpp_open(lxo_file[n], MPP_WRITE); sprintf(contact, "land_mosaic:tile%d::ocean_mosaic:tile%d", n+1, n+1); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec", "contact_type", "exchange", "parent1_cell", "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance"); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid"); mpp_end_def(fid); start[1] = 0; nwrite[0] = strlen(contact); mpp_put_var_value_block(fid, id_contact, start, nwrite, contact); nwrite[0] = nxgrid; mpp_put_var_value(fid, id_xgrid_area, area); mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di); start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj); mpp_close(fid); free(i1); free(j1); free(i2); free(j2); free(area); free(di); free(dj); } /*Fianlly create the coupler mosaic file mosaic_name.nc */ { int dim_string, dim_axo, dim_axl, dim_lxo, dims[2]; int id_amosaic_file, id_lmosaic_file, id_omosaic_file, id_otopog_file; int id_axo_file, id_axl_file, id_lxo_file; size_t start[4], nwrite[4]; for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } printf("mosaic_file is %s\n", mosaic_file); fid = mpp_open(mosaic_file, MPP_WRITE); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_axo = mpp_def_dim(fid, "nfile_aXo", ntiles); dim_axl = mpp_def_dim(fid, "nfile_aXl", ntiles); dim_lxo = mpp_def_dim(fid, "nfile_lXo", ntiles); id_amosaic_file = mpp_def_var(fid, "atm_mosaic_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "atmosphere_mosaic_file_name"); id_lmosaic_file = mpp_def_var(fid, "lnd_mosaic_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "land_mosaic_file_name"); id_omosaic_file = mpp_def_var(fid, "ocn_mosaic_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "ocean_mosaic_file_name"); id_otopog_file = mpp_def_var(fid, "ocn_topog_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "ocean_topog_file_name"); dims[0] = dim_axo; dims[1] = dim_string; id_axo_file = mpp_def_var(fid, "aXo_file", MPP_CHAR, 2, dims, 1, "standard_name", "atmXocn_exchange_grid_file"); dims[0] = dim_axl; dims[1] = dim_string; id_axl_file = mpp_def_var(fid, "aXl_file", MPP_CHAR, 2, dims, 1, "standard_name", "atmXlnd_exchange_grid_file"); dims[0] = dim_lxo; dims[1] = dim_string; id_lxo_file = mpp_def_var(fid, "lXo_file", MPP_CHAR, 2, dims, 1, "standard_name", "lndXocn_exchange_grid_file"); mpp_end_def(fid); nwrite[0] = strlen(lnd_mosaic); mpp_put_var_value_block(fid, id_lmosaic_file, start, nwrite, lnd_mosaic); mpp_put_var_value_block(fid, id_amosaic_file, start, nwrite, lnd_mosaic); mpp_put_var_value_block(fid, id_omosaic_file, start, nwrite, lnd_mosaic); for(n=0; n<ntiles; n++) { start[0] = n; nwrite[0] =1; nwrite[1] = strlen(ocn_topog_file[n]); mpp_put_var_value_block(fid, id_otopog_file, start, nwrite, ocn_topog_file[n]); nwrite[1] = strlen(axl_file[n]); mpp_put_var_value_block(fid, id_axl_file, start, nwrite, axl_file[n]); nwrite[1] = strlen(axo_file[n]); mpp_put_var_value_block(fid, id_axo_file, start, nwrite, axo_file[n]); nwrite[1] = strlen(lxo_file[n]); mpp_put_var_value_block(fid, id_lxo_file, start, nwrite, lxo_file[n]); } mpp_close(fid); } for(n=0; n<ntiles; n++) { free(axl_file[n]); free(axo_file[n]); free(lxo_file[n]); } free(axl_file); free(axo_file); free(lxo_file); printf("\n***** Congratulation! You have successfully run make_quick_mosaic\n"); mpp_end(); return 0; } /* main */
/******************************************************************************* 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 */
int main(int argc, char* argv[]) { char *mosaic_file = NULL, *topog_file = NULL, *topog_field = NULL; char topog_type[32] = "realistic", topog_mosaic[128] = "topog_mosaic"; char output_file[256]; int num_filter_pass = 1; int x_refine = 2, y_refine = 2; double basin_depth = 5000, bottom_depth = 5000, min_depth = 10, scale_factor = 1; double gauss_amp = 0.5, gauss_scale = 0.25, slope_x = 0, slope_y = 0; double bowl_south = 60, bowl_north = 70, bowl_west = 0, bowl_east = 20; int flat_bottom = 0, fill_first_row = 0; int filter_topog = 0, round_shallow = 0, fill_shallow = 0; int deepen_shallow = 0, smooth_topo_allow_deepening = 0; int errflg = (argc == 1); int option_index, i, c; /* * process command line */ static struct option long_options[] = { {"mosaic", required_argument, NULL, 'a'}, {"topog_type", required_argument, NULL, 'b'}, {"x_refine", required_argument, NULL, 'X'}, {"y_refine", required_argument, NULL, 'Y'}, {"basin_depth", required_argument, NULL, 'c'}, {"topog_file", required_argument, NULL, 'd'}, {"topog_field", required_argument, NULL, 'e'}, {"bottom_depth", required_argument, NULL, 'f'}, {"min_depth", required_argument, NULL, 'g'}, {"scale_factor", required_argument, NULL, 'i'}, {"num_filter_pass", required_argument, NULL, 'j'}, {"gauss_amp", required_argument, NULL, 'k'}, {"gauss_scale", required_argument, NULL, 'l'}, {"slope_x", required_argument, NULL, 'm'}, {"slope_y", required_argument, NULL, 'n'}, {"bowl_south", required_argument, NULL, 'p'}, {"bowl_north", required_argument, NULL, 'q'}, {"bowl_west", required_argument, NULL, 'r'}, {"bowl_east", required_argument, NULL, 's'}, {"fill_first_row", no_argument, NULL, 't'}, {"filter_topog", no_argument, NULL, 'u'}, {"round_shallow", no_argument, NULL, 'v'}, {"fill_shallow", no_argument, NULL, 'w'}, {"deepen_shallow", no_argument, NULL, 'x'}, {"smooth_topo_allow_deepening", no_argument, NULL, 'y'}, {"topog_mosaic", required_argument, NULL, 'o'}, {"help", no_argument, NULL, 'h'}, {0, 0, 0, 0}, }; /* start parallel */ mpp_init(&argc, &argv); mpp_domain_init(); while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) switch (c) { case 'a': mosaic_file = optarg; break; case 'b': strcpy(topog_type, optarg); break; case 'X': x_refine = atoi(optarg); break; case 'Y': y_refine = atoi(optarg); break; case 'c': basin_depth = atof(optarg); break; case 'd': topog_file = optarg; break; case 'e': topog_field = optarg; break; case 'f': bottom_depth = atof(optarg); break; case 'g': min_depth = atof(optarg); break; case 'i': scale_factor = atof(optarg); break; case 'j': num_filter_pass = atoi(optarg); break; case 'k': gauss_amp = atof(optarg); break; case 'l': gauss_scale = atof(optarg); break; case 'm': slope_x = atof(optarg); break; case 'n': slope_y = atof(optarg); break; case 'p': bowl_south = atof(optarg); break; case 'q': bowl_north = atof(optarg); break; case 'r': bowl_west = atof(optarg); break; case 's': bowl_east = atof(optarg); break; case 't': fill_first_row = 1; break; case 'u': filter_topog = 1; break; case 'v': round_shallow = 1; break; case 'w': fill_shallow = 1; break; case 'x': deepen_shallow = 1; break; case 'y': smooth_topo_allow_deepening = 1; break; case 'o': strcpy(topog_mosaic,optarg); break; case '?': errflg++; break; } if (errflg || !mosaic_file ) { char **u = usage; while (*u) { fprintf(stderr, "%s\n", *u); u++; } exit(2); } /* Write out arguments value */ if(mpp_pe() == mpp_root_pe()) printf("NOTE from make_topog ==> the topog_type is: %s\n",topog_type); if(x_refine != 2 || y_refine != 2 ) mpp_error("Error from make_topog: x_refine and y_refine should be 2, contact developer"); if(mpp_pe() == mpp_root_pe()) printf("NOTE from make_topog ==> x_refine is %d, y_refine is %d\n", x_refine, y_refine); if (strcmp(topog_type,"rectangular_basin") == 0) { if(mpp_pe() == mpp_root_pe()) printf("NOTE from make_topog ==> the basin depth is %f\n",basin_depth); } else if (strcmp(topog_type,"gaussian") == 0) { if(mpp_pe() == mpp_root_pe()){ printf("NOTE from make_topog ==> bottom_depth is: %f\n", bottom_depth ); printf("NOTE from make_topog ==> min_depth is: %f\n", min_depth ); printf("NOTE from make_topog ==> gauss_amp is: %f\n", gauss_amp ); printf("NOTE from make_topog ==> gauss_scale is: %f\n", gauss_scale ); printf("NOTE from make_topog ==> slope_x is: %f\n", slope_x ); printf("NOTE from make_topog ==> slope_y is: %f\n", slope_y ); } } else if(strcmp(topog_type,"bowl") == 0) { if(mpp_pe() == mpp_root_pe()){ printf("NOTE from make_topog ==> bottom_depth is: %f\n",bottom_depth); printf("NOTE from make_topog ==> min_depth is: %f\n",min_depth); printf("NOTE from make_topog ==> bowl_south is: %f\n",bowl_south); printf("NOTE from make_topog ==> bowl_north is: %f\n",bowl_north); printf("NOTE from make_topog ==> bowl_west is: %f\n",bowl_west); printf("NOTE from make_topog ==> bowl_east is: %f\n",bowl_east); } } else if(strcmp(topog_type,"idealized") == 0) { if(mpp_pe() == mpp_root_pe()){ printf("NOTE from make_topog ==> bottom_depth is: %f\n",bottom_depth); printf("NOTE from make_topog ==> min_depth is: %f\n",min_depth); } } else if(strcmp(topog_type,"realistic") == 0) { if(!topog_file || !topog_field) mpp_error("Error from make_topog: when topog_type is realistic, topog_file and topog_field must be specified."); if(mpp_pe() == mpp_root_pe()){ printf("NOTE from make_topog ==> bottom_depth is: %f\n",bottom_depth); printf("NOTE from make_topog ==> min_depth is: %f\n",min_depth); printf("NOTE from make_topog ==> topog_file is: %s\n", topog_file); printf("NOTE from make_topog ==> topog_field is: %s\n", topog_field); printf("NOTE from make_topog ==> scale_factor is: %f\n", scale_factor); printf("NOTE from make_topog ==> num_filter_pass is: %d\n", num_filter_pass); if(fill_first_row) printf("NOTE from make_topog ==>make first row of ocean model all land points.\n"); if(filter_topog) printf("NOTE from make_topog ==>will apply filter to topography.\n"); if(round_shallow) printf("NOTE from make_topog ==>Make cells land if depth is less than 1/2 " "mimumim depth, otherwise make ocean.\n"); if(fill_shallow) printf("NOTE from make_topog ==>Make cells less than minimum depth land.\n"); if(deepen_shallow) printf("NOTE from make_topog ==>Make cells less than minimum depth equal to minimum depth.\n"); if(smooth_topo_allow_deepening) printf("NOTE from make_topog ==>allow filter to deepen cells.\n"); } } else { mpp_error("make_topog: topog_type should be rectangular_basin, gaussian, bowl, idealized or realistic"); } if(mpp_pe() == mpp_root_pe()) { printf("**************************************************\n"); printf("Begin to generate topography \n"); } { int m_fid, g_fid, vid; int ntiles, fid, dim_ntiles, n, dims[2]; size_t start[4], nread[4], nwrite[4]; int *nx, *ny, *nxp, *nyp; int *id_depth; double *depth, *x, *y; int *t_fid; int dim_nchild, dim_string, id_mosaic, id_childfile; char **tile_files, **topog_files; char history[512]; char gridfile[256], griddir[256]; /* history will be write out as global attribute in output file to specify the command line arguments */ strcpy(history,argv[0]); for(i=1;i<argc;i++) { strcat(history, " "); strcat(history, argv[i]); } /* grid should be located in the same directory of mosaic file */ get_file_path(mosaic_file, griddir); /* get mosaic dimension */ m_fid = mpp_open(mosaic_file, MPP_READ); ntiles = mpp_get_dimlen( m_fid, "ntiles"); tile_files = (char **)malloc(ntiles*sizeof(char *)); topog_files = (char **)malloc(ntiles*sizeof(char *)); t_fid = (int *) malloc(ntiles*sizeof(int )); id_depth = (int *)malloc(ntiles*sizeof(int)); /* loop through each tile to get tile information and set up meta data for output file */ sprintf(output_file, "%s.nc", topog_mosaic); fid = mpp_open(output_file, MPP_WRITE); mpp_def_global_att(fid, GRID_VERSION_NAME, grid_version); mpp_def_global_att(fid, CODE_VERSION_NAME, tagname); mpp_def_global_att(fid, HISTORY_NAME, history); dim_nchild = mpp_def_dim(fid, NTILES_NAME, ntiles); dim_string = mpp_def_dim(fid, STRING_NAME, STRING); id_mosaic = mpp_def_var(fid, MOSAIC_FILES_NAME, MPP_CHAR, 1, &dim_string, 1, "standard_name", "grid_mosaic_files"); dims[0] = dim_nchild; dims[1] = dim_string; id_childfile = mpp_def_var(fid, TILE_FILES_NAME, MPP_CHAR, 2, dims, 0); mpp_end_def(fid); nx = (int *)malloc(ntiles*sizeof(int)); ny = (int *)malloc(ntiles*sizeof(int)); nxp = (int *)malloc(ntiles*sizeof(int)); nyp = (int *)malloc(ntiles*sizeof(int)); for( n = 0; n < ntiles; n++ ) { char tile_name[128]; tile_files[n] = (char *)malloc(STRING*sizeof(double)); topog_files[n] = (char *)malloc(STRING*sizeof(double)); start[0] = n; start[1] = 0; nread[0] = 1; nread[1] = STRING; vid = mpp_get_varid(m_fid, TILE_FILES_NAME); mpp_get_var_value_block(m_fid, vid, start, nread, gridfile); sprintf(tile_files[n], "%s/%s", griddir, gridfile); g_fid = mpp_open(tile_files[n], MPP_READ); vid = mpp_get_varid(g_fid, "tile"); mpp_get_var_value(g_fid, vid, tile_name); sprintf(topog_files[n],"%s.%s.nc", topog_mosaic, tile_name); nx[n] = mpp_get_dimlen(g_fid, "nx"); ny[n] = mpp_get_dimlen(g_fid, "ny"); if( nx[n]%x_refine != 0 ) mpp_error("make_topog: supergrid x-size can not be divided by x_refine"); if( ny[n]%y_refine != 0 ) mpp_error("make_topog: supergrid y-size can not be divided by y_refine"); nx[n] /= x_refine; ny[n] /= y_refine; nxp[n] = nx[n] + 1; nyp[n] = ny[n] + 1; t_fid[n] = mpp_open(topog_files[n], MPP_WRITE); mpp_def_global_att(t_fid[n], GRID_VERSION_NAME, grid_version); mpp_def_global_att(t_fid[n], CODE_VERSION_NAME, tagname); mpp_def_global_att(t_fid[n], HISTORY_NAME, history); dims[1] = mpp_def_dim(t_fid[n], NX_NAME, nx[n]); dims[0] = mpp_def_dim(t_fid[n], NY_NAME, ny[n]); id_depth[n] = mpp_def_var(t_fid[n], DEPTH_NAME, NC_DOUBLE, 2, dims, 2, "standard_name", "topographic depth at T-cell centers", "units", "meters"); mpp_close(g_fid); mpp_end_def(t_fid[n]); } mpp_close(m_fid); /* Generate topography and write out to the output_file */ for(n=0; n<ntiles; n++) { int layout[2], isc, iec, jsc, jec, nxc, nyc, ni, i, j; double *gdata, *tmp; domain2D domain; /* define the domain, each tile will be run on all the processors. */ mpp_define_layout( nx[n], ny[n], mpp_npes(), layout); mpp_define_domain2d( nx[n], ny[n], layout, 0, 0, &domain); mpp_get_compute_domain2d( domain, &isc, &iec, &jsc, &jec); nxc = iec - isc + 1; nyc = jec - jsc + 1; depth = (double *)malloc(nxc*nyc*sizeof(double)); x = (double *)malloc((nxc+1)*(nyc+1)*sizeof(double)); y = (double *)malloc((nxc+1)*(nyc+1)*sizeof(double)); tmp = (double *)malloc((nxc*x_refine+1)*(nyc*y_refine+1)*sizeof(double)); start[0] = jsc*y_refine; start[1] = isc*x_refine; nread[0] = nyc*y_refine+1; nread[1] = nxc*x_refine+1; ni = nxc*x_refine+1; g_fid = mpp_open(tile_files[n], MPP_READ); vid = mpp_get_varid(g_fid, "x"); mpp_get_var_value_block(g_fid, vid, start, nread, tmp); for(j = 0; j < nyc+1; j++) for(i = 0; i < nxc+1; i++) x[j*(nxc+1)+i] = tmp[(j*y_refine)*ni+i*x_refine]; vid = mpp_get_varid(g_fid, "y"); mpp_get_var_value_block( g_fid, vid, start, nread, tmp); mpp_close(g_fid); for(j = 0; j < nyc+1; j++) for(i = 0; i < nxc+1; i++) y[j*(nxc+1)+i] = tmp[(j*y_refine)*ni+i*x_refine]; if (strcmp(topog_type,"rectangular_basin") == 0) create_rectangular_topog(nx[n], ny[n], basin_depth, depth); else if (strcmp(topog_type,"gaussian") == 0) create_gaussian_topog(nx[n], ny[n], x, y, bottom_depth, min_depth, gauss_amp, gauss_scale, slope_x, slope_y, depth); else if (strcmp(topog_type,"bowl") == 0) create_bowl_topog(nx[n], ny[n], x, y, bottom_depth, min_depth, bowl_east, bowl_south, bowl_west, bowl_north, depth); else if (strcmp(topog_type,"idealized") == 0) create_idealized_topog( nx[n], ny[n], x, y, bottom_depth, min_depth, depth); else if (strcmp(topog_type,"realistic") == 0) create_realistic_topog(nxc, nyc, x, y, topog_file, topog_field, scale_factor, fill_first_row, filter_topog, num_filter_pass, smooth_topo_allow_deepening, round_shallow, fill_shallow, deepen_shallow, min_depth, depth ); gdata = (double *)malloc(nx[n]*ny[n]*sizeof(double)); mpp_global_field_double(domain, nxc, nyc, depth, gdata); mpp_put_var_value(t_fid[n], id_depth[n], gdata); free(x); free(y); free(tmp); free(depth); free(gdata); mpp_delete_domain2d(&domain); mpp_close(t_fid[n]); } for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } nwrite[0] = strlen(mosaic_file); mpp_put_var_value_block(fid, id_mosaic, start, nwrite, mosaic_file); nwrite[0] = 1; for(n=0; n<ntiles; n++) { start[0]=n; nwrite[1]=strlen(topog_files[n]); mpp_put_var_value_block(fid, id_childfile, start, nwrite, topog_files[n]); } mpp_close(fid); /*release memory */ free(id_depth); for(n=0; n<ntiles; n++) { free(tile_files[n]); free(topog_files[n]); } free(tile_files); free(topog_files); free(t_fid); free(nx); free(ny); free(nxp); free(nyp); } if(mpp_pe() == mpp_root_pe() ) printf("Successfully generate %s\n",output_file); mpp_end(); return 0; }; //main
/*********************************************************************** void create_grid_from_file( char *file, int *nlon, int *nlat, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx ) the grid location is defined through ascii file. calculate cell length, cell area and rotation angle ************************************************************************/ void create_grid_from_file( char *file, int *nlon, int *nlat, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx ) { double *xb, *yb, *xt, *yt, *xc, *yc; double p1[4], p2[4]; int nx, ny, nxp, nyp, ni, nj, i, j, n; FILE *pFile; char mesg[256], txt[128]; /************************************************************ identify the grid_file is ascii file or netcdf file, if the file name contains ".nc", it is a netcdf file, otherwise it is ascii file. *********************************************************/ nx = *nlon; ny = *nlat; nxp = nx + 1; nyp = ny + 1; if(strstr(file, ".nc") ) { int fid, vid; ni = *nlon/2; nj = *nlat/2; xc = (double *)malloc((ni+1)*(nj+1)*sizeof(double)); yc = (double *)malloc((ni+1)*(nj+1)*sizeof(double)); xt = (double *)malloc( ni * nj *sizeof(double)); yt = (double *)malloc( ni * nj *sizeof(double)); fid = mpp_open(file, MPP_READ); vid = mpp_get_varid(fid, "grid_lon"); mpp_get_var_value(fid, vid, xc); vid = mpp_get_varid(fid, "grid_lat"); mpp_get_var_value(fid, vid, yc); vid = mpp_get_varid(fid, "grid_lont"); mpp_get_var_value(fid, vid, xt); vid = mpp_get_varid(fid, "grid_latt"); mpp_get_var_value(fid, vid, yt); mpp_close(fid); for(j=0; j<nj+1; j++) for(i=0; i<ni+1; i++) { x[j*2*nxp+i*2] = xc[j*(ni+1)+i]; y[j*2*nxp+i*2] = yc[j*(ni+1)+i]; } for(j=0; j<nj; j++) for(i=0; i<ni; i++) { x[(j*2+1)*nxp+i*2+1] = xt[j*ni+i]; y[(j*2+1)*nxp+i*2+1] = yt[j*ni+i]; } for(j=0; j<nj+1; j++) for(i=0; i<ni; i++) { x[j*2*nxp+i*2+1] = (xc[j*(ni+1)+i]+xc[j*(ni+1)+i+1])*0.5; y[j*2*nxp+i*2+1] = (yc[j*(ni+1)+i]+yc[j*(ni+1)+i+1])*0.5; } for(j=0; j<nj; j++) for(i=0; i<ni+1; i++) { x[(j*2+1)*nxp+i*2] = (xc[j*(ni+1)+i]+xc[(j+1)*(ni+1)+i])*0.5; y[(j*2+1)*nxp+i*2] = (yc[j*(ni+1)+i]+yc[(j+1)*(ni+1)+i])*0.5; } for(j=0; j<nyp; j++) for(i=0; i<nx; i++) { p1[0] = x[j*nxp+i]; p2[0] = x[j*nxp+i+1]; p1[1] = y[j*nxp+i]; p2[1] = y[j*nxp+i+1]; dx[j*nx+i] = great_circle_distance(p1, p2); } for(j=0; j<ny; j++) for(i=0; i<nxp; i++) { p1[0] = x[j*nxp+i]; p2[0] = x[(j+1)*nxp+i]; p1[1] = y[j*nxp+i]; p2[1] = y[(j+1)*nxp+i]; dy[j*nxp+i] = great_circle_distance(p1, p2); } for(j=0; j<ny; j++) for(i=0; i<nx; i++) { p1[0] = x[j*nxp+i]; p1[1] = x[j*nxp+i+1]; p1[2] = x[(j+1)*nxp+i+1]; p1[3] = x[(j+1)*nxp+i]; p2[0] = y[j*nxp+i]; p2[1] = y[j*nxp+i+1]; p2[2] = y[(j+1)*nxp+i+1]; p2[3] = y[(j+1)*nxp+i]; area[j*nx+i] = poly_area(p1, p2, 4); } /* currently set angle to 0 */ for(j=0; j<nyp; j++) for(i=0; i<nxp; i++) angle_dx[j*nxp+i] = 0; free(xt); free(yt); free(xc); free(yc); } else { pFile = fopen (file,"r"); if(!pFile) { strcpy(mesg, "RegularSphericalGrid: Can not open ascii file "); strcat(mesg,file); mpp_error(mesg); } fscanf(pFile, "%s%*[^\n]",txt); /* header line (ignored) */ xb = (double *) malloc(nxp*sizeof(double)); yb = (double *) malloc(nyp*sizeof(double)); for(i=0;i<nxp;i++) fscanf(pFile, "%lg", xb+i); /* longitude */ fscanf(pFile, "%s%*[^\n]",txt); /* header line (ignored) */ for(j=0;j<nyp;j++) fscanf(pFile, "%lg", yb+j); /* latitude */ fclose(pFile); n=0; for(j=0; j<nyp; j++) { for(i=0; i<nxp; i++) { x[n] = xb[i]; y[n] = yb[j]; angle_dx[n++] = 0; } } /* zonal length */ n = 0; for(j=0; j<nyp; j++) { for(i=0; i<nx; i++ ) { dx[n++] = spherical_dist(x[j*nxp+i], y[j*nxp+i], x[j*nxp+i+1], y[j*nxp+i+1] ); } } /* meridinal length */ n = 0; for(j=0; j<ny; j++) { for(i=0; i<nxp; i++ ) { dy[n++] = spherical_dist(x[j*nxp+i], y[j*nxp+i], x[(j+1)*nxp+i], y[(j+1)*nxp+i] ); } } /* cell area */ n = 0; for(j=0; j<ny; j++) { for(i=0; i<nx; i++ ) { area[n++] = box_area(x[j*nxp+i]*D2R, y[j*nxp+i]*D2R, x[(j+1)*nxp+i+1]*D2R, y[(j+1)*nxp+i+1]*D2R ); } } free(xb); free(yb); } }; /* create_grid_from_file */