Пример #1
0
/*********************************************************************
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 */
Пример #2
0
/***************************************************************
 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 */
Пример #3
0
/***************************************************************************
 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);
    }
  }  
}
Пример #4
0
/********************************************************************************
  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 */
Пример #5
0
/****************************************************************
   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 */
Пример #6
0
/*********************************************************************
  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 */
Пример #7
0
/*********************************************************************
    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 */
Пример #8
0
/*******************************************************************
 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);
  }
}
Пример #9
0
/***************************************************************************
  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 */
Пример #10
0
/********************************************************************
  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;
}
Пример #11
0
/**********************************************************************
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 */
Пример #12
0
/*******************************************************************
 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);
  }

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

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

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

  switch(files[fid].var[vid].type) {
  case NC_DOUBLE:case NC_FLOAT:
    status = nc_put_vara_double(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;
  case NC_INT:
    status = nc_put_vara_int(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;
  case NC_SHORT:
    status = nc_put_vara_short(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;    
  case NC_CHAR:
    status = nc_put_vara_text(files[fid].ncid, files[fid].var[vid].fldid, start, nwrite, data);
    break;
  default:
    sprintf(errmsg, "mpp_io(mpp_put_var_value_block): field %s in file %s has an invalid type, "
	    "the type should be NC_DOUBLE, NC_FLOAT, NC_INT, NC_SHORT or NC_CHAR",
	    files[fid].var[vid].name, files[fid].name );
    mpp_error(errmsg);
  }    
  
  if(status != NC_NOERR) {
    sprintf(errmsg, "mpp_io(mpp_put_var_value_block): Error in putting value of variable %s from file %s",
	    files[fid].var[vid].name, files[fid].name );
    netcdf_error(errmsg, status);
  }
  
}; /* mpp_put_var_value_block */
Пример #16
0
/*********************************************************************
  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 */
Пример #17
0
/*********************************************************************
   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 */
Пример #18
0
/***************************************************************************
  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;
}
Пример #19
0
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;

} 
Пример #20
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 */
Пример #21
0
/********************************************************************
 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 */
Пример #22
0
/*********************************************************************
   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 */
Пример #23
0
/*********************************************************************
  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 */
Пример #24
0
/*
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;
    */
}
Пример #25
0
/*********************************************************************
  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 */
Пример #26
0
/* close the file */
void mpp_close(int fid)
{
  int status;
  char errmsg[512];

  if(fid == -1 && mpp_pe() != mpp_root_pe() ) return;
  
  if(fid<0 || fid >=nfiles) mpp_error("mpp_io(mpp_close): invalid id number, id should be "
				    "a nonnegative integer that less than nfiles");
  
  status = nc_close(files[fid].ncid);
  if(status != NC_NOERR) {
    sprintf( errmsg, "mpp_io(mpp_close): error in closing files %s ", files[fid].name);
    netcdf_error(errmsg, status);
  }
  files[fid].ncid = 0;
  files[fid].status = 0;
  
}
Пример #27
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 */
Пример #28
0
/********************************************************************
  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 */
Пример #30
0
int main(int argc, char* argv[])
{
  unsigned int opcode = 0;
  char    *mosaic_in=NULL;            /* input mosaic file name */
  char    *mosaic_out=NULL;           /* input mosaic file name */
  char    *dir_in=NULL;               /* input file location */
  char    *dir_out=NULL;              /* output file location */
  int     ntiles_in = 0;              /* number of tiles in input mosaic */
  int     ntiles_out = 0;             /* number of tiles in output mosaic */
  int     nfiles     = 0;              /* number of input file */
  int     nfiles_out = 0;             /* number of output file */
  char    input_file [NFILE][STRING];
  char    output_file[NFILE][STRING];
  char    scalar_name[NVAR] [STRING];
  char    u_name     [NVAR] [STRING];
  char    v_name     [NVAR] [STRING];
  char    *test_case = NULL;
  double  test_param = 1;
  int     check_conserve = 0; /* 0 means no check */
  double  lonbegin = 0, lonend = 360;
  double  latbegin = -90, latend = 90;			  
  int     nlon = 0, nlat = 0;
  int     kbegin = 0, kend = -1; 
  int     lbegin = 0, lend = -1;
  char    *remap_file = NULL;
  char    interp_method[STRING] = "conserve_order1";
  int     y_at_center = 0;
  int     grid_type = AGRID;
  int     nscalar=0, nvector=0, nvector2=0;
  int     option_index, c, i, n, m, l;
  char    entry[MAXSTRING];  /* should be long enough */
  char    txt[STRING];
  char    history[MAXATT];
  int     fill_missing = 0;
  unsigned int  finer_step = 0;

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

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

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

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

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

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

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


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

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

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

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

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

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


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

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

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

  if(mpp_pe() == mpp_root_pe() ) {
    printf("Successfully running fregrid and the following output file are generated.\n");
    for(n=0; n<ntiles_out; n++) {
      mpp_close(file_out[n].fid);
      printf("****%s\n", file_out[n].name);
      if( nfiles > 1 ) {
	mpp_close(file2_out[n].fid);
	printf("****%s\n", file2_out[n].name);
      }
    }
  }
      
  mpp_end();
  return 0;
  
} /* end of main */