/********************************************************************* void mpp_get_var_dimname(int fid, int vid, int i, char *name) For each dimension we are assuming there is a 1-d field have the same name as the dimension. *********************************************************************/ void mpp_get_var_dimname(int fid, int vid, int ind, char *name) { int status, ncid, fldid, ndims, dims[4]; char errmsg[512]; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_dimname): 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_get_var_dimname): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); ncid = files[fid].ncid; fldid = files[fid].var[vid].fldid; status = nc_inq_varndims(ncid, fldid, &ndims); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var2D_dimname): Error in getting ndims of var %s from file %s", files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } if(ind < 0 || ind >= ndims) mpp_error("mpp_io(mpp_get_var_dimname): invalid ind value, ind should be between 0 and ndim-1"); status = nc_inq_vardimid(ncid,fldid,dims); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var2D_dimname): Error in getting dimid of var %s from file %s", files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } status = nc_inq_dimname(ncid, dims[ind], name); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var2D_dimname): Error in getting %d dimension name of var %s from file %s", ind, files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } }; /* mpp_get_var_dimname */
/*************************************************************** void mpp_compute_extent(int npts, int ndivs, int *ibegin, int *iend) Compute extent of 1-D decomposition problem of dividing nx points into n domains maintaining symmetry i.e nx=18 n=4 4554 and 5445 are solutions but 4455 is not. this will always work for nx even n even or odd this will always work for nx odd, n odd this will never work for nx odd, n even: for this case we supersede the mirror calculation symmetrize = .NOT. ( mod(ndivs,2).EQ.0 .AND. mod(ieg-isg+1,2).EQ.1 ) nx even n odd fails if n>nx/2 ***************************************************************/ void mpp_compute_extent(int npts, int ndivs, int *ibegin, int *iend) { int ndivs_is_odd, npts_is_odd, symmetrize; int isg, ieg, is, ie; int imax, ndmax, ndmirror; int ndiv; if(ndivs > npts ) { mpp_error("mpp_compute_extent: more divisions requested than rows available. " ); } ndivs_is_odd = ndivs%2; npts_is_odd = npts%2; symmetrize = 0; if( ndivs_is_odd && npts_is_odd ) symmetrize = 1; if( ndivs_is_odd == 0 && npts_is_odd == 0 ) symmetrize = 1; if( ndivs_is_odd && npts_is_odd == 0 && ndivs < npts/2 ) symmetrize = 1; isg = 0; ieg = npts-1; is = isg; for(ndiv=0; ndiv<ndivs; ndiv++){ /*mirror domains are stored in the list and retrieved if required. */ if( ndiv == 0 ) { /* initialize max points and max domains */ imax = ieg; ndmax = ndivs; } /* do bottom half of decomposition, going over the midpoint for odd ndivs */ if( ndiv < (ndivs-1)/2+1 ) { /*domain is sized by dividing remaining points by remaining domains */ ie = is + ceil((imax-is+1.0)/(ndmax-ndiv) ) - 1; ndmirror = (ndivs-1) - ndiv; /* mirror domain */ if( ndmirror > ndiv && symmetrize ) { /* only for domains over the midpoint */ /*mirror extents, the max(,) is to eliminate overlaps */ ibegin[ndmirror] = max( isg+ieg-ie, ie+1 ); iend[ndmirror] = max( isg+ieg-is, ie+1 ); imax = ibegin[ndmirror] - 1; ndmax --; } } else { if( symmetrize ){ /*do top half of decomposition by retrieving saved values */ is = ibegin[ndiv]; ie = iend[ndiv]; } else { ie = is + ceil((imax-is+1.0)/(ndmax-ndiv)) - 1; } } ibegin[ndiv] = is; iend[ndiv] = ie; if( ie < is )mpp_error("mpp_domains(mpp_compute_extent): domain extents must be positive definite." ); if( ndiv == ndivs-1 && iend[ndiv] != ieg ) mpp_error( "mpp_domains(mpp_compute_extent): domain extents do not span space completely." ); is = ie + 1; } }; /* mpp_compute_extent */
/*************************************************************************** void mpp_get_var_bndname(int fid, int vid, char *bndname) Get the bound name of dimension variable if it exist, otherwise the value will be 'none' for time axis, the bounds may be 'climatology' **************************************************************************/ void mpp_get_var_bndname(int fid, int vid, char *bndname) { int ncid, fldid, status; char errmsg[512], name[32]; size_t siz; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_cart): 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_get_var_cart): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); ncid = files[fid].ncid; fldid = files[fid].var[vid].fldid; strcpy(name, "climatology"); status = nc_inq_attlen(ncid, fldid, name, &siz); if(status != NC_NOERR){ strcpy(name, "bounds"); status = nc_inq_attlen(ncid, fldid, name, &siz); } if(status != NC_NOERR){ strcpy(name, "edges"); status = nc_inq_attlen(ncid, fldid, name, &siz); } if(status != NC_NOERR) { strcpy(bndname, "none"); } else { status = nc_get_att_text(ncid, fldid, name, bndname); bndname[siz] = '\0'; if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var_bndname): Error in getting attribute %s of " "dimension variable %s from file %s", name, files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } } }
/******************************************************************************** void compute_grid_bound(int nb, const couble *bnds, const int *npts, int *grid_size, const char *center_cell) compute the 1-D grid location. ********************************************************************************/ double* compute_grid_bound(int nb, const double *bnds, const int *npts, int *grid_size, const char *center) { int refine, i, n, np; double *grid=NULL, *tmp=NULL; double *grid1=NULL, *grid2=NULL; if(!strcmp(center, "none") ) refine = 1; else if(!strcmp(center, "t_cell") || !strcmp(center, "c_cell") ) refine = 2; else mpp_error("tool_util: center should be 'none', 'c_cell' or 't_cell' "); grid1 = (double *)malloc(nb*sizeof(double)); grid1[0] = 1; n = 0; for(i=1; i<nb; i++) { if(npts[i-1]%refine) mpp_error("tool_util: when center_cell is not 'none', npts should be divided by 2"); n += npts[i-1]/refine; grid1[i] = n+1; } np = n + 1; *grid_size = n*refine; tmp = (double *)malloc(np*sizeof(double)); grid = (double *)malloc((*grid_size+1)*sizeof(double)); grid2 = (double *)malloc(np*sizeof(double)); for(i=0;i<np;i++) grid2[i] = i + 1.0; cubic_spline( nb, np, grid1, grid2, bnds, tmp, 1e30, 1e30); if(!strcmp(center, "none")) { for(i=0; i<np; i++) grid[i] = tmp[i]; } else if(!strcmp(center, "t_cell")) { for(i=0; i<np; i++) grid[2*i] = tmp[i]; for(i=0; i<n; i++) grid[2*i+1] = 0.5*(tmp[i]+tmp[i+1]); } else if( !strcmp(center, "c_cell")) { for(i=0; i<np; i++) grid[2*i] = tmp[i]; grid[1] = 0.5*(tmp[0]+tmp[1]); for(i=1; i<n; i++) grid[2*i+1] = 2*grid[2*i] - grid[2*i-1]; } free(grid1); free(grid2); free(tmp); return grid; };/* compute_grid_bound */
/**************************************************************** void mpp_get_shift(int sizex, int sizey, int *ishift, int *jshift) Return the shift value. For non-symmetry domain, ishift will be always 0. For symmetric domain, shift value can be 0 or 1 depending on position. ****************************************************************/ void mpp_get_shift(domain2D domain, int sizex, int sizey, int *ishift, int *jshift) { int nxc, nyc, nxd, nyd; nxc = domain.nxc; nyc = domain.nyc; nxd = domain.nxd; nyd = domain.nyd; if( (sizex == nxc && sizey == nyc) || (sizex == nxd && sizey == nyd) ) { *ishift = 0; *jshift = 0; } else if ( (sizex == nxc+1 && sizey == nyc) || (sizex == nxd+1 && sizey == nyd)) { *ishift = 1; *jshift = 0; } else if ( (sizex == nxc && sizey == nyc+1) || (sizex == nxd && sizey == nyd+1) ) { *ishift = 0; *jshift = 1; } else if ( (sizex == nxc+1 && sizey == nyc+1) || (sizex == nxd+1 && sizey == nyd+1) ) { *ishift = 1; *jshift = 1; } else mpp_error("mpp_domain: data should be on either compute or data domain."); }; /* mpp_get_shift */
/********************************************************************* void double bipolar_dist(double x1, double y1, double x2, double y2) return distance of bipolar grids *********************************************************************/ double bipolar_dist(double x1, double y1, double x2, double y2, double bpeq, double bpsp, double bpnp, double rp ) { double dist, x[2],y[2], bp_lon[2], bp_lat[2], metric[2]; double h1[2], h2[2], chic; int n; x[0] = x1; x[1] = x2; y[0] = y1; y[1] = y2; /*--- get the bipolar grid and metric term ----------------------------*/ for(n=0; n<2; n++){ bp_lon[n] = bp_lam(x[n],y[n],bpeq, rp); /* longitude (degrees) in bipolar grid system */ bp_lat[n] = bp_phi(x[n],y[n],bpsp, bpnp); /* latitude (degrees) in bipolar grid system */ h1[n] = RADIUS*cos(bp_lat[n]*D2R); h2[n] = RADIUS; metric[n] = 1.0; if (fabs(y[n]-90.0) < SMALL || fabs(bp_lon[n]*D2R) >= SMALL || fabs(bp_lat[n]*D2R) >= SMALL) { chic = acos(cos(bp_lon[n]*D2R)*cos(bp_lat[n]*D2R)); /* eqn. 6 */ metric[n] = rp*(1/pow(cos(chic/2),2))/(1+(pow(rp,2))*(pow(tan(chic/2),2)));/* eq 3 */ } } /*--- then calculate the distance -------------------------------------*/ if(x1 == x2) dist = distant(bp_lon[0],bp_lon[1],metric[0]*h1[0],metric[1]*h1[1]); else if(y1 == y2) dist = distant(bp_lat[0],bp_lat[1],metric[0]*h2[0],metric[1]*h2[1]); else mpp_error("tool_util: This tripolar grid not transformed from rectangular grid"); return dist; }; /* bipolar_dist */
/********************************************************************* void netcdf_error( int status ) status is the returning value of netcdf call. this routine will handle the error when status is not NC_NOERR. ********************************************************************/ void netcdf_error(const char *msg, int status ) { char errmsg[512]; sprintf( errmsg, "%s: %s", msg, nc_strerror(status) ); mpp_error(errmsg); }; /* netcdf_error */
/******************************************************************* void mpp_get_var_att_double(int fid, int vid, const char *name, double *val) get the attribute value of vid from file fid. ******************************************************************/ void mpp_get_var_att_double(int fid, int vid, const char *name, double *val) { int status; char errmsg[512]; nc_type type; short sval; int ival; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_att): 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_get_var_att): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); status = nc_inq_atttype(files[fid].ncid, files[fid].var[vid].fldid, name, &type); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var_att): Error in getting type of attribute %s of field %s in file %s ", name, files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } switch(type) { case NC_DOUBLE:case NC_FLOAT: status = nc_get_att_double(files[fid].ncid, files[fid].var[vid].fldid, name, val); break; case NC_INT: status = nc_get_att_int(files[fid].ncid, files[fid].var[vid].fldid, name, &ival); *val = ival; break; case NC_SHORT: status = nc_get_att_short(files[fid].ncid, files[fid].var[vid].fldid, name, &sval); *val = sval; break; default: sprintf(errmsg, "mpp_io(mpp_get_var_att): attribute %s of field %s in file %s has an invalid type, " "the type should be NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT or NC_CHAR", name, files[fid].var[vid].name, files[fid].name ); mpp_error(errmsg); } if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var_att): Error in getting value of attribute %s of variable %s from file %s", name, files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } }
/*************************************************************************** int mpp_var_att_exist(int fid, int vid, const char *att) check the field var has the attribute "att" or not. ***************************************************************************/ int mpp_var_att_exist(int fid, int vid, const char *att) { int status; size_t attlen; nc_type atttype; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_var_att_exist): 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_var_att_exist): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); status = nc_inq_att(files[fid].ncid, files[fid].var[vid].fldid, att, &atttype, &attlen); if(status == NC_NOERR) return 1; else return 0; }; /* mpp_att_exist */
/******************************************************************** int mpp_get_var_ndim(int fid, int vid) ********************************************************************/ int mpp_get_var_ndim(int fid, int vid) { int status, ndim; char errmsg[512]; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_ndim): 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_get_var_ndim): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); status = nc_inq_varndims(files[fid].ncid, files[fid].var[vid].fldid, &ndim); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_var_ndim): Error in getting ndims of var %s from file %s", files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } return ndim; }
/********************************************************************** void mpp_def_var_att(int fid, int vid, const char *attname, const char *attval) define one field attribute *********************************************************************/ void mpp_def_var_att(int fid, int vid, const char *attname, const char *attval) { int ncid, fldid, status; char errmsg[512]; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_def_var_att): 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_def_var_att): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); ncid = files[fid].ncid; fldid = files[fid].var[vid].fldid; status = nc_put_att_text(ncid,fldid,attname,strlen(attval),attval); if(status != NC_NOERR ) { sprintf(errmsg, "mpp_io(mpp_def_var_att): Error in put attribute %s of var %s of file %s", attname, files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } } /* mpp_def_var_att */
/******************************************************************* void mpp_get_global_att(int fid, const char *name, void *val) get the global attribute from file fid. ******************************************************************/ void mpp_get_global_att(int fid, const char *name, void *val) { int status; char errmsg[512]; nc_type type; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_global_att): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); status = nc_inq_atttype(files[fid].ncid, NC_GLOBAL, name, &type); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_global_att): Error in getting type of global attribute %s in file %s ", name, files[fid].name ); netcdf_error(errmsg, status); } switch(type) { case NC_DOUBLE:case NC_FLOAT: status = nc_get_att_double(files[fid].ncid, NC_GLOBAL, name, val); break; case NC_INT: status = nc_get_att_int(files[fid].ncid, NC_GLOBAL, name, val); break; case NC_SHORT: status = nc_get_att_short(files[fid].ncid, NC_GLOBAL, name, val); break; case NC_CHAR: status = nc_get_att_text(files[fid].ncid, NC_GLOBAL, name, val); break; default: sprintf(errmsg, "mpp_io(mpp_get_global_att): global attribute %s in file %s has an invalid type, " "the type should be NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT or NC_CHAR", name, files[fid].name ); mpp_error(errmsg); } if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_global_att): Error in getting value of global attribute %s from file %s", name, files[fid].name ); netcdf_error(errmsg, status); } }
/********************************************************************** 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 */
/********************************************************************* void mpp_get_var_value(int fid, int vid, void *data) read part of var data, the part is defined by start and nread. *********************************************************************/ void mpp_get_var_value(int fid, int vid, void *data) { int status; int *data_i4; short *data_i2; float *data_r4; char errmsg[512]; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_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_get_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_get_var_double(files[fid].ncid, files[fid].var[vid].fldid, data); break; case NC_INT: status = nc_get_var_int(files[fid].ncid, files[fid].var[vid].fldid, data); break; case NC_SHORT: status = nc_get_var_short(files[fid].ncid, files[fid].var[vid].fldid, data); break; case NC_CHAR: status = nc_get_var_text(files[fid].ncid, files[fid].var[vid].fldid, data); break; default: sprintf(errmsg, "mpp_io(mpp_get_var_value): 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_get_var_value): Error in getting value of variable %s from file %s", files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } }; /* mpp_get_var_value */
/********************************************************************* void mpp_redef(int fid) redef the meta data of netcdf file with fid. *******************************************************************/ void mpp_redef(int fid) { int status; char errmsg[512]; if( mpp_pe() != mpp_root_pe() ) return; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_redef): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); status = nc_redef(files[fid].ncid); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_redef): Error in redef the meta data of file %s", files[fid].name ); netcdf_error(errmsg, status); } } /* mpp_redef */
/*************************************************************************** char mpp_get_var_cart(int fid, int vid) get the cart of the dimension variable *************************************************************************/ char mpp_get_var_cart(int fid, int vid) { char cart; int ncid, fldid, status; char errmsg[512]; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_var_cart): 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_get_var_cart): invalid vid number, vid should be " "a nonnegative integer that less than nvar"); cart = 'N'; ncid = files[fid].ncid; fldid = files[fid].var[vid].fldid; status = nc_get_att_text(ncid, fldid, "cartesian_axis", &cart); if(status != NC_NOERR)status = nc_get_att_text(ncid, fldid, "axis", &cart); if(status != NC_NOERR){ sprintf(errmsg, "mpp_io(mpp_get_var_cart): Error in getting attribute cartesian_axis/axis of " "dimension variable %s from file %s", files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } return cart; }
int mpp_var_exist(int fid, const char *field) { int status, varid; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_var_exist): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); status = nc_inq_varid(files[fid].ncid, field, &varid); if(status == NC_NOERR) return 1; else return 0; }
/********************************************************************* int mpp_get_varid(int fid, const char *varname) get the id of the varname from file with fid, the id will be the index in files[fid].var. *********************************************************************/ int mpp_get_varid(int fid, const char *varname) { int status, fldid, vid, n; char errmsg[512]; /* First look through existing variables to see if the fldid of varname is already retrieved. */ if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_varid): invalid id number, id should be " "a nonnegative integer that less than nfiles"); for(n=0; n<files[fid].nvar; n++) { if( !strcmp(files[fid].var[n].name, varname) ) return n; } vid = files[fid].nvar; files[fid].nvar++; if(files[fid].nvar > MAXVAR ) mpp_error("mpp_io(mpp_get_varid): nvar is larger than MAXVAR, increase MAXVAR"); status = nc_inq_varid(files[fid].ncid, varname, &fldid); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_varid): error in get field_id of variable %s from file %s", varname, files[fid].name); netcdf_error(errmsg, status); } status = nc_inq_vartype(files[fid].ncid, fldid, &(files[fid].var[vid].type)); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_varid): Error in getting type of of field %s in file %s ", files[fid].var[vid].name, files[fid].name ); netcdf_error(errmsg, status); } files[fid].var[vid].fldid = fldid; strcpy(files[fid].var[vid].name, varname); return vid; };/* mpp_get_varid */
/******************************************************************** int mpp_def_dim(int fid, char* name, int size) define dimension. ********************************************************************/ int mpp_def_dim(int fid, const char* name, int size) { int dimid, status; char errmsg[512]; if( mpp_pe() != mpp_root_pe() ) return 0; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_def_dim): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); status = nc_def_dim(files[fid].ncid, name, size, &dimid); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_def_dim): Error in defining dimension %s of file %s", name, files[fid].name ); netcdf_error(errmsg, status); } return dimid; } /* mpp_def_dim */
/********************************************************************* void mpp_end_def(int ncid) end the definition of netcdf file with ncid. *******************************************************************/ void mpp_end_def(int fid) { int status; char errmsg[512]; if( mpp_pe() != mpp_root_pe() ) return; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_end_def): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); if(HEADER_BUFFER_VALUE>0) status = nc__enddef(files[fid].ncid, HEADER_BUFFER_VALUE, 4, 0, 4); else status = nc_enddef(files[fid].ncid); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_end_def): Error in end definition of file %s", files[fid].name ); netcdf_error(errmsg, status); } } /* mpp_end_def */
/********************************************************************* void mpp_def_global_att(int fid, const char *name, const char *val) write out global attribute ********************************************************************/ void mpp_def_global_att(int fid, const char *name, const char *val) { size_t status; char errmsg[512]; if( mpp_pe() != mpp_root_pe() ) return; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_def_global_att): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); status = nc_put_att_text(files[fid].ncid, NC_GLOBAL, name, strlen(val), val); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_def_global_att): Error in put glboal attribute %s of file %s", name, files[fid].name ); netcdf_error(errmsg, status); } }; /* mpp_def_global_att */
/* Fonction : Description: Return: */ war9a w7al(joumla name, ra9m mode){ war9a w; w = NULL; switch(mode){ case 1: w = xw7al(name,"r"); break; case 2: w = xw7al(name,"w"); break; default: mpp_error("Unknown mode !\n"); break; } return w; /* ra9m fd; FILEE *fp; if (*mode != 'r' && *mode != 'w' && *mode != 'a') return NULL; for (fp = _iob; fp < _iob + OPEN_MAX; fp++) if ((fp->flag & (_READ | _WRITE)) == 0) break; if (fp >= _iob + OPEN_MAX) return NULL; if (*mode == 'w') fd = creat(name, PERMS); else if (*mode == 'a') { if ((fd = open(name, O_WRONLY, 0)) == -1) fd = creat(name, PERMS); lseek(fd, 0L, 2); } else fd = open(name, O_RDONLY, 0); if (fd == -1) return NULL; fp->fd = fd; fp->cnt = 0; fp->base = NULL; fp->flag = (*mode == 'r') ? _READ : _WRITE; return fp; */ }
/********************************************************************* int mpp_get_dimid(int fid, const char *dimname) get the id of the dimname from file with fid, *********************************************************************/ int mpp_get_dimid(int fid, const char *dimname) { int status, dimid; char errmsg[512]; /* First look through existing variables to see if the fldid of varname is already retrieved. */ if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_dimid): invalid id number, id should be " "a nonnegative integer that less than nfiles"); status = nc_inq_dimid(files[fid].ncid, dimname, &dimid); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_dimid): error in get dimension id of %s from file %s", dimname, files[fid].name); netcdf_error(errmsg, status); } return dimid; };/* mpp_get_dimid */
/* 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; }
double spherical_dist(double x1, double y1, double x2, double y2) { double dist = 0.0; double h1, h2; if(x1 == x2) { h1 = RADIUS; h2 = RADIUS; dist = distant(y1,y2,h1,h2); } else if(y1 == y2) { h1 = RADIUS * cos(y1*D2R); h2 = RADIUS * cos(y2*D2R); dist = distant(x1,x2,h1,h2); } else mpp_error("tool_till: This is not rectangular grid"); return dist; }; /* spherical_dist */
/******************************************************************** int mpp_get_dimlen(char* file, char *name) Get the dimension. *******************************************************************/ int mpp_get_dimlen(int fid, const char *name) { int ncid, dimid, status, len; size_t size; char errmsg[512]; if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_get_dimlen): invalid fid number, fid should be " "a nonnegative integer that less than nfiles"); ncid = files[fid].ncid; status = nc_inq_dimid(ncid, name, &dimid); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_dimlen): error in inquiring dimid of %s from file %s", name, files[fid].name); netcdf_error(errmsg, status); } status = nc_inq_dimlen(ncid, dimid, &size); if(status != NC_NOERR) { sprintf(errmsg, "mpp_io(mpp_get_dimlen): error in inquiring dimlen of %s from file %s", name, files[fid].name); netcdf_error(errmsg, status); } len = size; return len; }; /* mpp_get_dimlen */
/******************************************************************************* void create_conformal_cubic_grid( int *npoints, int *nratio, char *method, char *orientation, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx, double *angle_dy ) create cubic grid. All six tiles grid will be generated. *******************************************************************************/ void create_conformal_cubic_grid( int *npts, int *nratio, char *method, char *orientation, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx, double *angle_dy ) { int nx, ny, nxp, nyp; nx = *npts; ny = nx; nxp = nx+1; nyp = nxp; /*calculate geographic coordinates. */ if(strcmp(orientation, "center_pole") == 0) calc_geocoords_centerpole(nx, ny, x, y); else mpp_error("create_cubic_grid: only center pole orientation is implemented"); /* calculate cell length and area */ calc_fvgrid(nx, ny, *nratio, dx, dy, area); /*calculate rotation angle, just some workaround, will modify this in the future. */ calc_rotation_angle(nxp, nyp, x, y, angle_dx, angle_dy ); }; /* create_conformal_cubic_grid */
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 */