/* 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; }
/********************************************************************** 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 */
/******************************************************************** 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 */
/********************************************************************* 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 */
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 */
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; }
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
/******************************************************************************* 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 */
/******************************************************************************* 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 */
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
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
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; }
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 */
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 */