#include #include #include #include "topog.h" #include "create_xgrid.h" #include "mosaic_util.h" #include "mpp_io.h" #define D2R (M_PI/180.) void filter_topo( int nx, int ny, int num_pass, int smooth_topo_allow_deepening, double *depth); void set_depth(int nx, int ny, const double *xbnd, const double *ybnd, double alat1, double slon1, double elon1, double alat2, double slon2, double elon2, double depth_in, double *depth); void enforce_min_depth(int nx, int ny, int round_shallow, int deepen_shallow, int fill_shallow, double min_depth, double *depth); /********************************************************************* void create_rectangular_topog() Constructing a rectangular basin with a flat bottom, basin_depth can be 0 ( all land). ********************************************************************/ void create_rectangular_topog(int nx, int ny, double basin_depth, double *depth) { int i; for(i=0; i= bowl_east || yy <= bowl_south || yy >= bowl_north) bottom = min_depth; else bottom = min_depth + bottom_depth*(1.0-exp(-pow((yy-bowl_south)/2.0,2))) *(1.0-exp(-pow((yy-bowl_north)/2.0,2))) *(1.0-exp(-pow((xx-bowl_west)/4.0,2))) *(1.0-exp(-pow((xx-bowl_east)/4.0,2))); depth[j*nx+i] = bottom; } } }; /* create_bowl_topog */ /********************************************************************* void create_gaussian_topog() Constructing a gaussian bump ********************************************************************/ void create_gaussian_topog(int nx, int ny, const double *x, const double *y, double bottom_depth, double min_depth, double gauss_amp, double gauss_scale, double slope_x, double slope_y, double *depth) { double bump_height, bump_scale, xcent, ycent, arg, bottom; double xe, xw, ys, yn; double *xt, *yt; int i, j, nxp, nyp; xt = (double *)malloc(nx*ny*sizeof(double)); yt = (double *)malloc(nx*ny*sizeof(double)); for(j=0; j 0.0 ) { arg = bottom_depth*(1-0.4*fabs(cos(((j+1)*M_PI)/nyp)*sin(((i+1)*2*M_PI)/nxp))); arg = max(arg, min_depth); depth[j*nx+i] = arg; } } } // add "idealized" ridges arg = 0.666*bottom_depth; set_depth (nx, ny, xbnd, ybnd, -20.0, 360.0-20.0, 360.0-10.0, 30.0, 360.0-45.0, 360.0-35.0, arg, depth); set_depth (nx, ny, xbnd, ybnd, 30.0, 360.0-45.0, 360.0-35.0, 60.0, 360.0-20.0, 360.0-30.0, arg, depth); set_depth (nx, ny, xbnd, ybnd, -60.0,360.0-100.0, 360.0-130.0, 40.0, 360.0-160.0, 180.0, arg, depth); arg = 0.5*bottom_depth; set_depth (nx, ny, xbnd, ybnd, -50.0, 360.0-120.0, 360.0-120.0, 30.0, 190.0, 190.0, arg, depth); free(xbnd); free(ybnd); } /* create_idealized_topog */ /********************************************************************* void set_depth(double alat1, double slon1, double elon1, double alat2, double slon2, double elon2, double depth_in ) set the topography depth "depth[i][j](i,j)" = "depth_in" within the area of the trapezoid bounded by vertices: (alat1,slon1), (alat1,elon1), (alat2,slon2), and (alat2,elon2) inputs: alat1 = southern latitude of trapezoid (degrees) slon1 = starting longitude of southern edge of trapezoid (deg) elon1 = ending longitude of southern edge of trapezoid (deg) alat2 = northern latitude of trapezoid (degrees) slon2 = starting longitude of northern edge of trapezoid (deg) elon2 = ending longitude of northern edge of trapezoid (deg) depth_in = constant depth value ********************************************************************/ void set_depth(int nx, int ny, const double *xbnd, const double *ybnd, double alat1, double slon1, double elon1, double alat2, double slon2, double elon2, double depth_in, double *depth) { double rdj, d; int i, j, i1, i2, j1, j2, is, ie, js, je, is1, ie1, is2, ie2; j1 = nearest_index(alat1, ybnd, ny ); j2 = nearest_index(alat2, ybnd, ny ); js = min(j1,j2); je = max(j1,j2); i1 = nearest_index(slon1, xbnd, nx); i2 = nearest_index(elon1, xbnd, nx); is1 = min(i1,i2); ie1 = max(i1,i2); i1 = nearest_index(slon2, xbnd, nx ); i2 = nearest_index(elon2, xbnd, ny ); is2 = min(i1,i2); ie2 = max(i1,i2); is = is1; ie = ie1; // fill in the area bounded by (js,is1), (js,ie1), (je,is2), (je,ie2) // the nudging of 1.e-5 is to insure that the test case resolution // generates the same topography and geometry on various computers. if (js == je) rdj = 1.0; else rdj = 1.0/(je-js); for(j=js;j<=je;j++){ for(i=is;i<=ie;i++) depth[j*nx+i] = depth_in; d = rdj*((j-js)*is2 + (je-j)*is1) + 1.0e-5; is = ceil(d); if( is - d > 0.5) is = is -1; d = rdj*((j-js)*ie2 + (je-j)*ie1) + 1.0e-5; ie = ceil(d); if( ie - d > 0.5) ie = ie -1; } }; /* set_depth */ /********************************************************************* void create_realistic_topog( ) reading data from source data file topog_file and remap it onto current grid ********************************************************************/ void create_realistic_topog(int nx_dst, int ny_dst, const double *x_dst, const double *y_dst, const char* topog_file, const char* topog_field, double scale_factor, double fill_first_row, int filter_topog, int num_filter_pass, int smooth_topo_allow_deepening, int round_shallow, int fill_shallow, int deepen_shallow, double min_depth, double *depth ) { char xname[128], yname[128]; int nx_src, ny_src, nxp_src, nyp_src, i, j, count, n; double *depth_src, *mask_src, *xt_src, *yt_src, *x_src, *y_src; double *x_out, *y_out; double missing; int fid, vid; /* first read source topography data to get source grid and source topography */ fid = mpp_open(topog_file, MPP_READ); vid = mpp_get_varid(fid, topog_field); mpp_get_var_dimname(fid, vid, 1, xname); mpp_get_var_dimname(fid, vid, 0, yname); nx_src = mpp_get_dimlen( fid, xname ); ny_src = mpp_get_dimlen( fid, yname ); nxp_src = nx_src + 1; nyp_src = ny_src + 1; depth_src = (double *)malloc(nx_src*ny_src*sizeof(double)); mask_src = (double *)malloc(nx_src*ny_src*sizeof(double)); xt_src = (double *)malloc(nx_src*sizeof(double)); yt_src = (double *)malloc(ny_src*sizeof(double)); x_src = (double *)malloc(nxp_src*nyp_src*sizeof(double)); y_src = (double *)malloc(nxp_src*nyp_src*sizeof(double)); mpp_get_var_att(fid, vid, "missing_value", &missing); mpp_get_var_value(fid, vid, depth_src); vid = mpp_get_varid(fid, xname); mpp_get_var_value(fid, vid, xt_src); vid = mpp_get_varid(fid, yname); mpp_get_var_value(fid, vid, yt_src); mpp_close(fid); for(j=0; j 1) mpp_error("topog: at most one of round_shallow/deepen_shallow/fill_shallow can be set to true"); if(count>0) enforce_min_depth(nx_dst, ny_dst, round_shallow, deepen_shallow, fill_shallow, min_depth, depth); free(depth_src); free(mask_src); free(x_src); free(y_src); free(xt_src); free(yt_src); free(x_out); free(y_out); }; /* create_realistic_topog */ /********************************************************************* void filter_topo( int nx, int ny, int num_pass, double *depth) smooth topographic depth "d" with "num_pass" applications of a 2D version of a shapiro filter (weights = 1/4, 1/2, 1/4) . allow filtering to decrease the bottom depth but not increase it. do not allow original geometry to change. note: depth "d" should be on a grid of uniformly constant spacing ********************************************************************/ void filter_topo( int nx, int ny, int num_pass, int smooth_topo_allow_deepening, double *depth) { double *rmask, *s; double f[9], d_old; int n1, n2, i, j, n, m, ip, jp; size_t *dims; rmask = (double *)malloc(nx*ny*sizeof(double)); s = (double *)malloc(nx*ny*sizeof(double)); /* 2D symmetric filter weights */ f[0] = 1.0/16.0; f[1] = 1.0/8.0; f[2] = 1.0/16.0; f[3] = 1.0/8.0; f[4] = 1.0/4.0; f[5] = 1.0/8.0; f[6] = 1.0/16.0; f[7] = 1.0/8.0; f[8] = 1.0/16.0; /* geometry mask */ for(i=0; i d_old) s[j*nx+i] = d_old; } s[j*nx+i] = s[j*nx+i]*rmask[j*nx+i]; } } for(i=0; i= min_depth. ********************************************************************/ void enforce_min_depth(int nx, int ny, int round_shallow, int deepen_shallow, int fill_shallow, double min_depth, double *depth) { int i, j, n, l; if(mpp_pe() == mpp_root_pe() ) printf(" Enforcing the minimum topography depth to be %f\n",min_depth); n = 0; if(round_shallow) { for(j=0;j