#include #include #include #include #include #include "mpp.h" #include "mosaic_util.h" #include "interp.h" #include "tool_util.h" #include "constant.h" #include "create_hgrid.h" #define D2R (M_PI/180.) #define R2D (180./M_PI) /********************************************************************************* some private routines used in this file *********************************************************************************/ void set_regular_lonlat_grid( int nxp, int nyp, int isc, int iec, int jsc, int jec, double *xb, double *yb, double *x, double *y, double *dx, double *dy, double *area, double *angle, int use_great_circle_algorithm); void set_f_plane_grid( int nxp, int nyp, int isc, int iec, int jsc, int jec, double *xb, double *yb, double f_plane_latitude, double *x, double *y, double *dx, double *dy, double *area, double *angle); double cartesian_dist(double x1, double y1, double x2, double y2, double f_plane_latitude); double cartesian_box_area(double x1, double y1, double x2, double y2, double f_plane_latitude); /************************************************************************************ void create_regular_lonlat_grid( int *nxbnds, int *nybnds, double *xbnds, double *ybnds, int *nlon, int *nlat, int *isc, int *iec, int *jsc, int *jec, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx, int use_great_circle_algorithm ) calculate grid location, length, area and rotation angle. The routine takes the following arguments INPUT: OUTPUT: ************************************************************************************/ void create_regular_lonlat_grid( int *nxbnds, int *nybnds, double *xbnds, double *ybnds, int *nlon, int *nlat, double *dlon, double *dlat, int use_legacy, int *isc, int *iec, int *jsc, int *jec, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx, const char *center, int use_great_circle_algorithm) { int nx, ny, nxp, nyp, nxb, nyb; double *xb=NULL, *yb=NULL; int refine; double stretch = 1; /* use cubic-spline interpolation algorithm to calculate nominal zonal grid location. */ nxb = *nxbnds; nyb = *nybnds; if( use_legacy ) { xb = compute_grid_bound_legacy(nxb, xbnds, dlon, stretch, &nx, center); yb = compute_grid_bound_legacy(nyb, ybnds, dlat, stretch, &ny, center); } else { xb = compute_grid_bound(nxb, xbnds, nlon, &nx, center); yb = compute_grid_bound(nyb, ybnds, nlat, &ny, center); } nxp = nx + 1; nyp = ny + 1; /* Test if left and right hand resolutions differ. Inform user of potential problem. */ if ( fabs(xb[1] - xb[0] - xb[nx] + xb[nx-1])/(xb[1] - xb[0]) > 1.e-6 ) { printf("%d\n",nxp); printf("%s\n" ,"Note: End point resolutions differ for x-axis. Not suitable for periodic axes"); printf("%s\n" ," See documentation for generating periodic axes when center = 'c_cell'"); } if ( fabs(yb[1] - yb[0] - yb[ny] + yb[ny-1])/(yb[1] - yb[0]) > 1.e-6 ) { printf("%d\n",nyp); printf("%s\n" ,"Note: End point resolutions differ for y-axis. Not suitable for periodic axes"); printf("%s\n" ," See documentation for generating periodic axes when center = 'c_cell'"); } set_regular_lonlat_grid( nxp, nyp, *isc, *iec, *jsc, *jec, xb, yb, x, y, dx, dy, area, angle_dx, use_great_circle_algorithm); free(xb); free(yb); }; /* create_regular_lonlat_grid */ /************************************************************************************ void create_simple_cartesian_grid( double *xbnds, double *ybnds, int *nlon, int *nlat, double *simple_dx, *simple_dy, int *isc, int *iec, int *jsc, int *jec, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx ) calculate grid location, length, area and rotation angle. The routine takes the following arguments INPUT: OUTPUT: ************************************************************************************/ void create_simple_cartesian_grid( double *xbnds, double *ybnds, int *nlon, int *nlat, double *simple_dx, double *simple_dy, int *isc, int *iec, int *jsc, int *jec, double *x, double *y, double *dx, double *dy, double *area, double *angle_dx ) { int nx, ny, nxp, nyp, i, j, n, nxc, nyc, nxb, nyb; double *grid1=NULL, *grid2=NULL, *xb=NULL, *yb=NULL; nxb = 2; nyb = 2; nx = *nlon; ny = *nlat; nxp = nx + 1; nyp = ny + 1; /* use cubic-spline interpolation algorithm to calculate nominal zonal grid location. */ xb = (double *)malloc(nxp*sizeof(double)); grid1 = (double *)malloc(nxb*sizeof(double)); grid1[0] = 1; grid1[1] = nxp; grid2 = (double *)malloc(nxp*sizeof(double)); for(i=0;i 1.e-6 ) { printf("%d\n",nxp); printf("%s\n" ,"Note: End point resolutions differ for x-axis. Not suitable for periodic axes"); printf("%s\n" ," See documentation for generating periodic axes when center = 'c_cell'"); } n = 0; for(j=0; j 1.e-6 ) { printf("%d\n",nxp); printf("%s\n" ,"Note: End point resolutions differ for x-axis. Not suitable for periodic axes"); printf("%s\n" ," See documentation for generating periodic axes when center = 'c_cell'"); } if ( fabs(yb[1] - yb[0] - yb[ny] + yb[ny-1])/(yb[1] - yb[0]) > 1.e-6 ) { printf("%d\n",nyp); printf("%s\n" ,"Note: End point resolutions differ for y-axis. Not suitable for periodic axes"); printf("%s\n" ," See documentation for generating periodic axes when center = 'c_cell'"); } set_f_plane_grid( nxp, nyp, *isc, *iec, *jsc, *jec, xb, yb, f_plane_latitude, x, y, dx, dy, area, angle_dx); free(xb); free(yb); }; /* create_f_plane_grid */ /* distance between cartesian grid on the earth */ double cartesian_dist(double x1, double y1, double x2, double y2, double f_plane_latitude) { double dist = 0.0; if(x1 == x2) dist = fabs(y2-y1)*D2R*RADIUS; else if(y1 == y2) dist = fabs(x2-x1)*D2R*RADIUS*cos(f_plane_latitude*D2R); else mpp_error("create_lonlat_grid: This is not rectangular grid"); return dist; } /* rectangular grid box area for cartesian grid */ double cartesian_box_area(double x1, double y1, double x2, double y2, double f_plane_latitude) { double area=0; double dx, dy; dx = x2-x1; dx = dx * D2R; dy = y2-y1; dy = dy * D2R; area = dx*dy*cos(f_plane_latitude*D2R)*RADIUS*RADIUS; return area; }