#include #include #include #include #include "read_mosaic.h" #include "constant.h" #include "mosaic_util.h" #ifdef use_netCDF #include #endif /********************************************************************* 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 handle_netcdf_error(const char *msg, int status ) { char errmsg[512]; sprintf( errmsg, "%s: %s", msg, nc_strerror(status) ); error_handler(errmsg); }; /* handle_netcdf_error */ /*************************************************************************** void get_file_dir(const char *file, char *dir) get the directory where file is located. The dir will be the complate path before the last "/". If no "/" exist in file, the path will be current ".". ***************************************************************************/ void get_file_dir(const char *file, char *dir) { int len; char *strptr = NULL; /* get the diretory */ strptr = strrchr(file, '/'); if(strptr) { len = strptr - file; strncpy(dir, file, len); } else { len = 1; strcpy(dir, "."); } dir[len] = 0; }; /* get_file_dir */ int field_exist(const char* file, const char *name) { int ncid, varid, status, existed; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "field_exist: in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_varid(ncid, name, &varid); if(status == NC_NOERR) existed = 1; else existed = 0; status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "field_exist: in closing file %s.", file); handle_netcdf_error(msg, status); } return existed; #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif return 0; }; /* field_exist */ int get_dimlen(const char* file, const char *name) { int ncid, dimid, status, len; size_t size; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_dimid(ncid, name, &dimid); if(status != NC_NOERR) { sprintf(msg, "in getting dimid of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_inq_dimlen(ncid, dimid, &size); if(status != NC_NOERR) { sprintf(msg, "in getting dimension size of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "in closing file %s.", file); handle_netcdf_error(msg, status); } len = size; if(status != NC_NOERR) { sprintf(msg, "in closing file %s", file); handle_netcdf_error(msg, status); } #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif return len; }; /* get_dimlen */ /******************************************************************************* void get_string_data(const char *file, const char *name, char *data) get string data of field with "name" from "file". ******************************************************************************/ void get_string_data(const char *file, const char *name, char *data) { int ncid, varid, status; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_varid(ncid, name, &varid); if(status != NC_NOERR) { sprintf(msg, "in getting varid of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_get_var_text(ncid, varid, data); if(status != NC_NOERR) { sprintf(msg, "in getting data of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "in closing file %s.", file); handle_netcdf_error(msg, status); } #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif }; /* get_string_data */ /******************************************************************************* void get_string_data_level(const char *file, const char *name, const size_t *start, const size_t *nread, char *data) get string data of field with "name" from "file". ******************************************************************************/ void get_string_data_level(const char *file, const char *name, char *data, const int *level) { int ncid, varid, status, i; size_t start[4], nread[4]; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_varid(ncid, name, &varid); if(status != NC_NOERR) { sprintf(msg, "in getting varid of %s from file %s.", name, file); handle_netcdf_error(msg, status); } for(i=0; i<4; i++) { start[i] = 0; nread[i] = 1; } start[0] = *level; nread[1] = STRING; status = nc_get_vara_text(ncid, varid, start, nread, data); if(status != NC_NOERR) { sprintf(msg, "in getting data of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "in closing file %s.", file); handle_netcdf_error(msg, status); } #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif }; /* get_string_data_level */ /******************************************************************************* void get_int_data(const char *file, const char *name, int *data) get int data of field with "name" from "file". ******************************************************************************/ void get_int_data(const char *file, const char *name, int *data) { int ncid, varid, status; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_varid(ncid, name, &varid); if(status != NC_NOERR) { sprintf(msg, "in getting varid of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_get_var_int(ncid, varid, data); if(status != NC_NOERR) { sprintf(msg, "in getting data of %s from file %s", name, file); handle_netcdf_error(msg, status); } status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "in closing file %s.", file); handle_netcdf_error(msg, status); } #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif }; /* get_int_data */ /******************************************************************************* void get_double_data(const char *file, const char *name, double *data) get double data of field with "name" from "file". ******************************************************************************/ void get_double_data(const char *file, const char *name, double *data) { int ncid, varid, status; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_varid(ncid, name, &varid); if(status != NC_NOERR) { sprintf(msg, "in getting varid of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_get_var_double(ncid, varid, data); if(status != NC_NOERR) { sprintf(msg, "in getting data of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "in closing file %s.", file); handle_netcdf_error(msg, status); } #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif }; /* get_double_data */ /****************************************************************************** void get_var_text_att(const char *file, const char *name, const char *attname, char *att) get text attribute of field 'name' from 'file ******************************************************************************/ void get_var_text_att(const char *file, const char *name, const char *attname, char *att) { int ncid, varid, status; char msg[512]; #ifdef use_netCDF status = nc_open(file, NC_NOWRITE, &ncid); if(status != NC_NOERR) { sprintf(msg, "in opening file %s", file); handle_netcdf_error(msg, status); } status = nc_inq_varid(ncid, name, &varid); if(status != NC_NOERR) { sprintf(msg, "in getting varid of %s from file %s.", name, file); handle_netcdf_error(msg, status); } status = nc_get_att_text(ncid, varid, attname, att); if(status != NC_NOERR) { sprintf(msg, "in getting attribute %s of %s from file %s.", attname, name, file); handle_netcdf_error(msg, status); } status = nc_close(ncid); if(status != NC_NOERR) { sprintf(msg, "in closing file %s.", file); handle_netcdf_error(msg, status); } #else error_handler("read_mosaic: Add flag -Duse_netCDF when compiling"); #endif }; /* get_var_text_att */ /*********************************************************************** return number of overlapping cells. ***********************************************************************/ #ifndef __AIX int read_mosaic_xgrid_size_( const char *xgrid_file ) { return read_mosaic_xgrid_size(xgrid_file); } #endif int read_mosaic_xgrid_size( const char *xgrid_file ) { int ncells; ncells = get_dimlen(xgrid_file, "ncells"); return ncells; } /****************************************************************************/ #ifndef __AIX void read_mosaic_xgrid_order1_(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area ) { read_mosaic_xgrid_order1(xgrid_file, i1, j1, i2, j2, area); }; #endif void read_mosaic_xgrid_order1(const char *xgrid_file, int *i1, int *j1, int *i2, int *j2, double *area ) { int ncells, n; int *tile1_cell, *tile2_cell; double garea; ncells = get_dimlen(xgrid_file, "ncells"); tile1_cell = (int *)malloc(ncells*2*sizeof(int)); tile2_cell = (int *)malloc(ncells*2*sizeof(int)); get_int_data(xgrid_file, "tile1_cell", tile1_cell); get_int_data(xgrid_file, "tile2_cell", tile2_cell); get_double_data(xgrid_file, "xgrid_area", area); garea = 4*M_PI*RADIUS*RADIUS; for(n=0; n '9' || pstring[m][l] < '0' ) { error_handler("Error from read_mosaic: some of the character in " "contact_indices except token is not digit number"); } } istart1[n] = atoi(pstring[0]); iend1[n] = atoi(pstring[1]); jstart1[n] = atoi(pstring[2]); jend1[n] = atoi(pstring[3]); istart2[n] = atoi(pstring[4]); iend2[n] = atoi(pstring[5]); jstart2[n] = atoi(pstring[6]); jend2[n] = atoi(pstring[7]); if(istart1[n] == iend1[n] ) { istart1[n] = (istart1[n]+1)/x_refine-1; iend1[n] = istart1[n]; if( jend1[n] > jstart1[n] ) { jstart1[n] -= 1; jend1[n] -= y_refine; } else if( jend1[n] < jstart1[n] ) { jstart1[n] -= y_refine; jend1[n] -= 1; } else error_handler("Error from read_mosaic_contact: jstart1 and jend1 should not be equal when istart1=iend1"); if(jstart1[n]%y_refine || jend1[n]%y_refine) error_handler("Error from read_mosaic_contact: mismatch between y_refine and jstart1/jend1 when istart1=iend1"); jstart1[n] /= y_refine; jend1[n] /= y_refine; } else if( jstart1[n] == jend1[n] ) { jstart1[n] = (jstart1[n]+1)/y_refine-1; jend1[n] = jstart1[n]; if(iend1[n] > istart1[n] ) { istart1[n] -= 1; iend1[n] -= x_refine; } else if(istart1[n] > iend1[n] ) { istart1[n] -= x_refine; iend1[n] -= 1; } else error_handler("Error from read_mosaic_contact: istart1 and iend1 should not be equal when jstart1=jend1"); if(istart1[n]%x_refine || iend1[n]%x_refine) error_handler("Error from read_mosaic_contact: mismatch between x_refine and istart1/iend1 when jstart1=jend1"); istart1[n] /= x_refine; iend1[n] /= x_refine; } else { error_handler("Error from read_mosaic_contact: only line contact is supported now, contact developer"); } if(istart2[n] == iend2[n] ) { istart2[n] = (istart2[n]+1)/x_refine-1; iend2[n] = istart2[n]; if( jend2[n] > jstart2[n] ) { jstart2[n] -= 1; jend2[n] -= y_refine; } else if( jstart2[n] > jend2[n] ) { jstart2[n] -= y_refine; jend2[n] -= 1; } else error_handler("Error from read_mosaic_contact: jstart2 and jend2 should not be equal when istart2=iend2"); if(jstart2[n]%y_refine || jend2[n]%y_refine ) error_handler("Error from read_mosaic_contact: mismatch between y_refine and jstart2/jend2 when istart2=iend2"); jstart2[n] /= y_refine; jend2[n] /= y_refine; } else if( jstart2[n] == jend2[n] ) { jstart2[n] = (jstart2[n]+1)/y_refine-1; jend2[n] = jstart2[n]; if(iend2[n] > istart2[n] ) { istart2[n] -= 1; iend2[n] -= x_refine; } else if(istart2[n] > iend2[n] ) { istart2[n] -= x_refine; iend2[n] -= 1; } else error_handler("Error from read_mosaic_contact: istart2 and iend2 should not be equal when jstart2=jend2"); if(istart2[n]%x_refine || iend2[n]%x_refine) error_handler("Error from read_mosaic_contact: mismatch between x_refine and istart2/iend2 when jstart2=jend2"); istart2[n] /= x_refine; iend2[n] /= x_refine; } else { error_handler("Error from read_mosaic_contact: only line contact is supported now, contact developer"); } } }; /* read_mosaic_contact */ /****************************************************************************** void read_mosaic_grid_data(const char *mosaic_file, const char *name, int nx, int ny, double *data, int level, int ioff, int joff) read mosaic grid information onto model grid. We assume the refinement is 2 right now. We may remove this restriction in the future. nx and ny are model grid size. level is the tile number. ioff and joff to indicate grid location. ioff =0 and joff = 0 for C-cell. ioff=0 and joff=1 for E-cell, ioff=1 and joff=0 for N-cell, ioff=1 and joff=1 for T-cell ******************************************************************************/ void read_mosaic_grid_data(const char *mosaic_file, const char *name, int nx, int ny, double *data, int level, int ioff, int joff) { char tilefile[STRING], gridfile[STRING], dir[STRING]; double *tmp; int ni, nj, nxp, nyp, i, j; get_file_dir(mosaic_file, dir); get_string_data_level(mosaic_file, "gridfiles", gridfile, &level); sprintf(tilefile, "%s/%s", dir, gridfile); ni = get_dimlen(tilefile, "nx"); nj = get_dimlen(tilefile, "ny"); if( ni != nx*2 || nj != ny*2) error_handler("supergrid size should be double of the model grid size"); tmp = (double *)malloc((ni+1)*(nj+1)*sizeof(double)); get_double_data( tilefile, name, tmp); nxp = nx + 1 - ioff; nyp = ny + 1 - joff; for(j=0; j