/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! !! !! GNU General Public License !! !! !! !! This file is part of the Flexible Modeling System (FMS). !! !! !! !! FMS is free software; you can redistribute it and/or modify !! !! it and are expected to follow the terms of the GNU General Public !! !! License as published by the Free Software Foundation. !! !! !! !! FMS is distributed in the hope that it will be useful, !! !! but WITHOUT ANY WARRANTY; without even the implied warranty of !! !! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the !! !! GNU General Public License for more details. !! !! !! !! You should have received a copy of the GNU General Public License !! !! along with FMS; if not, write to: !! !! Free Software Foundation, Inc. !! !! 59 Temple Place, Suite 330 !! !! Boston, MA 02111-1307 USA !! !! or see: !! !! http://www.gnu.org/licenses/gpl.txt !! !! !! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ #include #include #include #include #include "fregrid_util.h" #include "mpp.h" #include "mpp_io.h" #include "tool_util.h" #include "mosaic_util.h" #include "read_mosaic.h" #include "gradient_c2l.h" #include "globals.h" #define D2R (M_PI/180) #define R2D (180/M_PI) #define EPSLN (1.e-10) void init_halo(double *var, int nx, int ny, int nz, int halo); void update_halo(int nx, int ny, int nz, double *data, Bound_config *bound, Data_holder *dHold); void setup_boundary(const char *mosaic_file, int ntiles, Grid_config *grid, Bound_config *bound, int halo, int position); void delete_bound_memory(int ntiles, Bound_config *bound); void copy_var_config(const Var_config *var_in, Var_config *var_out); void init_var_config(Var_config *var, int interp_method); /******************************************************************************* void setup_tile_data_file(Mosaic_config mosaic, const char *filename) This routine will setup the data file name for each tile. *******************************************************************************/ void set_mosaic_data_file(int ntiles, const char *mosaic_file, const char *dir, File_config *file, const char *filename) { char str1[STRING]="", str2[STRING]="", tilename[STRING]=""; int i, n, len, fid, vid; size_t start[4], nread[4]; len = strlen(filename); if( strstr(filename, ".nc") ) strncpy(str1, filename, len-3); else strcpy(str1, filename); if(dir) { if(strlen(dir)+strlen(str1) >= STRING)mpp_error("set_mosaic_data_file(fregrid_util): length of str1 + " "length of dir should be no greater than STRING"); sprintf(str2, "%s/%s", dir, str1); } else strcpy(str2, str1); for(i=0; i<4; i++) { start[i] = 0; nread[i] = 1; } nread[1] = STRING; if(ntiles > 1) { if(!mosaic_file) mpp_error("fregrid_util: when ntiles is greater than 1, mosaic_file should be defined"); fid = mpp_open(mosaic_file, MPP_READ); vid = mpp_get_varid(fid, "gridtiles"); } for(i = 0; i < ntiles; i++) { start[0] = i; if(ntiles > 1) { mpp_get_var_value_block(fid, vid, start, nread, tilename); if(strlen(str2) + strlen(tilename) > STRING -5) mpp_error("set_mosaic_data_file(fregrid_util): length of str2 + " "length of tilename should be no greater than STRING-5"); sprintf(file[i].name, "%s.%s.nc", str2, tilename); } else sprintf(file[i].name, "%s.nc", str2); } }; /* setup_data_file */ /******************************************************************************* void set_scalar_var() *******************************************************************************/ void set_field_struct(int ntiles, Field_config *field, int nvar, char * varname, File_config *file) { int n, i; if(nvar == 0) return; for(n=0; n0) { init_halo(grid[n].lonc, nx[n]+1, ny[n]+1, 1, halo); init_halo(grid[n].latc, nx[n]+1, ny[n]+1, 1, halo); } for(j=0; j<=ny[n]; j++) for(i=0; i<=nx[n]; i++) { ind1 = (j+halo)*(nx[n]+1+2*halo)+i+halo; ind2 = 2*j*(2*nx[n]+1)+2*i; grid[n].lonc[ind1] = x[ind2]*D2R; grid[n].latc[ind1] = y[ind2]*D2R; } for(j=0; j EPSLN) grid[n].rotate = 1; } free(angle); } } free(x); free(y); mpp_close(g_fid); } mpp_close(m_fid); /* get the boundary condition */ setup_boundary(mosaic_file, ntiles, grid, bound_T, 1, CENTER); if(opcode & BILINEAR) setup_boundary(mosaic_file, ntiles, grid, bound_C, 1, CORNER); for(n=0; n 0 ) { dHold = (Data_holder *)malloc(nbound*sizeof(Data_holder)); for(l=0; l 0) { dHold = (Data_holder *)malloc(nbound*sizeof(Data_holder)); for(l=0; l EPSLN) grid[n].rotate = 1; } free(angle); } } mpp_close(g_fid); } mpp_close(m_fid); free(nx); free(ny); }; /* get_output_grid_from_mosaic*/ /******************************************************************************* void get_output_grid_by_size(Mosaic_config *mosaic, int nlon, int nlat, int finer_steps, unsigned int opcode) calculate output grid based on nlon, nlat and finer steps. *******************************************************************************/ void get_output_grid_by_size(int ntiles, Grid_config *grid, double lonbegin, double lonend, double latbegin, double latend, int nlon, int nlat, int finer_steps, int center_y, unsigned int opcode) { double dlon, dlat, lon_fine, lat_fine, lon_range, lat_range; int nx_fine, ny_fine, i, j, layout[2]; int nxc, nyc, ii, jj; if(ntiles !=1) mpp_error("fregrid_utils: ntiles of output mosaic must be 1 for bilinear interpolation"); if(finer_steps && !(opcode&BILINEAR)) mpp_error("fregrid_util: finer_steps must be 0 when interp_method is not bilinear"); grid->nx = nlon; grid->ny = nlat; grid->nx_fine = pow(2,finer_steps)*nlon; grid->ny_fine = pow(2,finer_steps)*(nlat-1)+1; nx_fine = grid->nx_fine; ny_fine = grid->ny_fine; lon_range = lonend - lonbegin; lat_range = latend - latbegin; grid->lont1D = (double *)malloc(nlon*sizeof(double)); grid->latt1D = (double *)malloc(nlat*sizeof(double)); grid->lonc1D = (double *)malloc((nlon+1)*sizeof(double)); grid->latc1D = (double *)malloc((nlat+1)*sizeof(double)); dlon=lon_range/nlon; for(i=0; ilont1D[i] = (lonbegin + (i + 0.5)*dlon)*D2R; for(i=0; i<=nlon; i++) grid->lonc1D[i] = (lonbegin + i*dlon)*D2R; layout[0] = 1; layout[1] = mpp_npes(); mpp_define_domain2d(grid->nx, grid->ny, layout, 0, 0, &(grid->domain)); mpp_get_compute_domain2d(grid->domain, &(grid->isc), &(grid->iec), &(grid->jsc), &(grid->jec)); grid->nxc = grid->iec - grid->isc + 1; grid->nyc = grid->jec - grid->jsc + 1; nxc = grid->nxc; nyc = grid->nyc; if(center_y) { dlat=lat_range/nlat; for(j=0; jlatt1D[j] = (latbegin+(j+0.5)*dlat)*D2R; for(j=0; j<=nlat; j++) grid->latc1D[j] = (latbegin+j*dlat)*D2R; } else { dlat=lat_range/(nlat-1); for(j=0; jlatt1D[j] = (latbegin+j*dlat)*D2R; for(j=0; j<=nlat; j++) grid->latc1D[j] = (latbegin+(j-0.5)*dlat)*D2R; } if(opcode & BILINEAR) { grid->latt1D_fine = (double *)malloc(ny_fine*sizeof(double)); grid->lont = (double *)malloc(nx_fine*ny_fine*sizeof(double)); grid->latt = (double *)malloc(nx_fine*ny_fine*sizeof(double)); grid->xt = (double *)malloc(nx_fine*ny_fine*sizeof(double)); grid->yt = (double *)malloc(nx_fine*ny_fine*sizeof(double)); grid->zt = (double *)malloc(nx_fine*ny_fine*sizeof(double)); grid->vlon_t = (double *)malloc(3*nx_fine*ny_fine*sizeof(double)); grid->vlat_t = (double *)malloc(3*nx_fine*ny_fine*sizeof(double)); dlon = lon_range/nx_fine; for(i=0; ilont[j*nx_fine+i] = lon_fine; } if(center_y) { dlat=lat_range/ny_fine; for(j=0; jlatt1D_fine[j] = (latbegin+(j+0.5)*dlat)*D2R; } else { dlat = lat_range/(ny_fine-1); for(j=0; jlatt1D_fine[j] = (latbegin+j*dlat)*D2R; } for(j=0; jlatt[j*nx_fine+i] = grid->latt1D_fine[j]; } /* get the cartesian coordinates */ latlon2xyz(nx_fine*ny_fine, grid->lont, grid->latt, grid->xt, grid->yt, grid->zt); unit_vect_latlon(nx_fine*ny_fine, grid->lont, grid->latt, grid->vlon_t, grid->vlat_t); } else { /* for conservative interpolation */ grid->lonc = (double *) malloc((nxc+1)*(nyc+1)*sizeof(double)); grid->latc = (double *) malloc((nxc+1)*(nyc+1)*sizeof(double)); for(j=0; j<=nyc; j++) { jj = j + grid->jsc; for(i=0; i<=nxc; i++) { ii = i + grid->isc; grid->lonc[j*(nxc+1)+i] = grid->lonc1D[ii]; grid->latc[j*(nxc+1)+i] = grid->latc1D[jj]; } } if(opcode & VECTOR) { /* no rotation is needed for regular lat-lon grid. */ grid->rotate = 0; } } }; /* get_output_grid_by_size */ /******************************************************************************* void init_var_config(Var_config *var) *******************************************************************************/ void init_var_config(Var_config *var, int interp_method) { var->nz = 1; var->nn = 1; var->has_naxis = 0; var->has_zaxis = 0; var->has_taxis = 0; var->kstart = 0; var->kend = 0; var->lstart = 0; var->lend = 0; var->ndim = 0; var->interp_method = interp_method; } /******************************************************************************* void copy_var_config(Var_config *var) *******************************************************************************/ void copy_var_config(const Var_config *var_in, Var_config *var_out) { int i; var_out->nz = var_in->nz; var_out->nn = var_in->nn; var_out->has_naxis = var_in->has_naxis; var_out->has_zaxis = var_in->has_zaxis; var_out->has_taxis = var_in->has_taxis; var_out->kstart = var_in->kstart; var_out->kend = var_in->kend ; var_out->lstart = var_in->lstart; var_out->lend = var_in->lend; var_out->ndim = var_in->ndim; var_out->interp_method = var_in->interp_method; for(i=0; indim; i++) var_out->index[i] = var_in->index[i]; } /******************************************************************************* void get_input_metadata(Mosaic_config, *mosaic) *******************************************************************************/ void get_input_metadata(int ntiles, int nfiles, File_config *file1, File_config *file2, Field_config *scalar, Field_config *u_comp, Field_config *v_comp, const Grid_config *grid, int kbegin, int kend, int lbegin, int lend, unsigned int opcode) { int n, m, i, l, ll, nscalar, nvector, nfield; int ndim, dimsize[4], nz; nc_type type[5]; char cart[5]; char dimname[5][STRING], bndname[5][STRING], errmsg[STRING]; File_config *file = NULL; Field_config *field = NULL; size_t start[4], nread[4]; int interp_method, use_bilinear, use_conserve; char remap_method[STRING]; use_bilinear = 0; use_conserve = 0; if(opcode & CONSERVE_ORDER1) { use_conserve = 1; interp_method = CONSERVE_ORDER1; } else if(opcode & CONSERVE_ORDER2) { use_conserve = 1; interp_method = CONSERVE_ORDER2; } else if(opcode & BILINEAR) { use_bilinear = 1; interp_method = BILINEAR; } /* First find out how many fields in file and file2. */ nscalar = 0; nvector = 0; if( scalar) nscalar = scalar->nvar; if( u_comp) nvector = u_comp->nvar; for(n=0; n<4; n++) { start[n] = 0; nread[n] = 1; } for(m=0; m5) mpp_error("get_input_metadata(fregrid_util.c): ndim should be no less than 2 and no larger than 5"); for(i=0; i 2) { if(cart[ndim-3] == 'Z') { field[n].var[ll].has_zaxis = 1; field[n].var[ll].nz = dimsize[ndim-3]; if(kend > field[n].var[ll].nz) { sprintf(errmsg, "get_input_metadata(fregrid_util.c): KlevelEnd should be no larger than " "number of vertical levels of field %s in file %s.", field[n].var[ll].name, file[n].name); mpp_error(errmsg); } if(kbegin>0) { field[n].var[ll].kstart = kbegin - 1; field[n].var[ll].kend = kend - 1; field[n].var[ll].nz = kend - kbegin + 1; } else { field[n].var[ll].kstart = 0; field[n].var[ll].kend = field[n].var[ll].nz - 1; } } else if(cart[ndim-3] == 'N') { field[n].var[ll].has_naxis = 1; field[n].var[ll].nn = dimsize[ndim-3]; } } if(ndim > 3) { if(cart[ndim-4] == 'Z') { mpp_error("get_input_metadata(fregrid_util.c): the Z-axis must be the third dimension"); } if(cart[ndim-4] == 'N') { field[n].var[ll].has_naxis = 1; field[n].var[ll].nn = dimsize[ndim-4]; } } if(cart[0] == 'T') { field[n].var[ll].has_taxis = 1; if(lend > dimsize[0]) { sprintf(errmsg, "get_input_metadata(fregrid_util.c): LstepEnd should be no larger than " "number of time levels of field %s in file %s.", field[n].var[ll].name, file[n].name); mpp_error(errmsg); } if(lbegin>0) { field[n].var[ll].lstart = lbegin - 1; field[n].var[ll].lend = lend - 1; file[n].nt = lend - lbegin + 1; } else { field[n].var[ll].lstart = 0; field[n].var[ll].lend = dimsize[0] - 1; file[n].nt = dimsize[0]; } } for(i=0; i MAXDIM) mpp_error("get_input_metadata(fregrid_util.c):ndim is greater than MAXDIM"); file[n].axis[j].cart = cart[i]; file[n].axis[j].type = type[i]; strcpy(file[n].axis[j].name, dimname[i]); strcpy(file[n].axis[j].bndname, bndname[i]); file[n].axis[j].vid = mpp_get_varid(file[n].fid, dimname[i]); if(cart[i] == 'T') { start[0] = field[n].var[ll].lstart; file[n].axis[j].size = file[n].nt; } else if(cart[i] == 'Z') { start[0] = field[n].var[ll].kstart; file[n].axis[j].size = field[n].var[ll].nz; } else { start[0] = 0; file[n].axis[j].size = dimsize[i]; } file[n].axis[j].data = (double *)malloc(file[n].axis[j].size*sizeof(double)); nread[0] = file[n].axis[j].size; mpp_get_var_value_block(file[n].fid, file[n].axis[j].vid, start, nread, file[n].axis[j].data); file[n].axis[j].bndtype = 0; if(strcmp(bndname[i], "none") ) { file[n].axis[j].bndid = mpp_get_varid(file[n].fid, bndname[i]); if(mpp_get_var_ndim(file[n].fid,file[n].axis[j].bndid) == 1) { file[n].axis[j].bndtype = 1; file[n].axis[j].bnddata = (double *)malloc((file[n].axis[j].size+1)*sizeof(double)); nread[0] = file[n].axis[j].size+1; } else { file[n].axis[j].bndtype = 2; file[n].axis[j].bnddata = (double *)malloc(2*file[n].axis[j].size*sizeof(double)); nread[0] = file[n].axis[j].size; nread[1] = 2; } mpp_get_var_value_block(file[n].fid, file[n].axis[j].bndid, start, nread, file[n].axis[j].bnddata); } } } /*ndim*/ } /* nvar */ } /* ntile */ /* make sure the consistency between tiles */ for(n=1; n 0) start[0] = lbegin-1; else start[0] = 0; nread[0] = file[n].nt; nread[1] = 1; mpp_get_var_value_block(file[n].fid, file[n].id_t1, start, nread, file[n].t1); mpp_get_var_value_block(file[n].fid, file[n].id_t2, start, nread, file[n].t2); mpp_get_var_value_block(file[n].fid, file[n].id_dt, start, nread, file[n].dt); } } } /*nfile*/ /* make sure bilinear and conservative interpolation do not co-exist. */ if(use_bilinear && use_conserve) mpp_error("get_input_metadata(fregrid_util.c): bilinear interpolation and conservative " "interpolation can not co-exist, check you option interp_method in command " "line and field attribute interp_method in source file"); }; /* get_input_metadata */ /******************************************************************************* void set_output_metadata ( Mosaic_config *mosaic) *******************************************************************************/ void set_output_metadata (int ntiles_in, int nfiles, const File_config *file1_in, const File_config *file2_in, const Field_config *scalar_in, const Field_config *u_in, const Field_config *v_in, int ntiles_out, File_config *file1_out, File_config *file2_out, Field_config *scalar_out, Field_config *u_out, Field_config *v_out, const Grid_config *grid_out, const char *history, const char *tagname) { int m, n, ndim, i, l, dims[5]; int dim_bnds, dim_time; int nscalar, nvector; const File_config *file_in = NULL; File_config *file_out = NULL; nscalar = 0; nvector = 0; if( scalar_in) nscalar = scalar_in->nvar; if( u_in) nvector = u_in->nvar; for(n=0; nnvar; for(l=0; lnvar; l++) { field_out[n].var[l].missing = field_in->var[l].missing; field_out[n].var[l].scale = field_in->var[l].scale; field_out[n].var[l].offset = field_in->var[l].offset; } } /******************************************************************************* void set_remap_file( ) *******************************************************************************/ void set_remap_file( int ntiles, const char *mosaic_file, const char *remap_file, Interp_config *interp, unsigned int *opcode, int save_weight_only) { int i, len, m, fid, vid; size_t start[4], nread[4]; char str1[STRING], tilename[STRING]; int file_exist; if(!remap_file) return; for(i=0; i<4; i++) { start[i] = 0; nread[i] = 1; } nread[1] = STRING; len = strlen(remap_file); if(len >= STRING) mpp_error("setoutput_remap_file(fregrid_util): length of remap_file should be less than STRING"); if( strstr(remap_file, ".nc") ) { strncpy(str1, remap_file, len-3); str1[len-3] = 0; } else strcpy(str1, remap_file); (*opcode) |= WRITE; if(ntiles>1) { fid = mpp_open(mosaic_file, MPP_READ); vid = mpp_get_varid(fid, "gridtiles"); } for(m=0; m 1) { start[0] = m; mpp_get_var_value_block(fid, vid, start, nread, tilename); if(strlen(str1) + strlen(tilename) > STRING -5) mpp_error("set_output_remap_file(fregrid_util): length of str1 + " "length of tilename should be no greater than STRING-5"); sprintf(interp[m].remap_file, "%s.%s.nc", str1, tilename); } else sprintf(interp[m].remap_file, "%s.nc", str1); /* check xgrid file to be read (=1) or write ( = 2) */ if(!save_weight_only && mpp_file_exist(interp[m].remap_file)) { (*opcode) |= READ; interp[m].file_exist = 1; } } if(ntiles>1) mpp_close(fid); };/* set_remap_file */ /*---------------------------------------------------------------------- void write_output_axis_data( ) write out time axis data of the output data file --------------------------------------------------------------------*/ void write_output_time(int ntiles, File_config *file, int level) { int i, n; size_t start[4], nwrite[4]; for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } start[0] = level; if( mpp_pe() == mpp_root_pe()) { for(n=0; nvar[varid].interp_method; if(interp_method == CONSERVE_ORDER1) halo = 0; else halo = 1; ndim = field->var[varid].ndim; if(ndim < 2) mpp_error("fregrid_util(get_input_data): ndim must be no less than 2"); nread = (size_t *)malloc(ndim*sizeof(size_t)); start = (size_t *)malloc(ndim*sizeof(size_t)); for(i=0; ivar[varid].has_taxis) start[pos++] = level_t; if(field->var[varid].has_naxis) start[pos++] = level_n; if(field->var[varid].has_zaxis) start[pos++] = level_z; if(ndim != pos + 2) mpp_error("fregrid_util(get_input_data): mimstch between ndim and has_taxis/has_zaxis/has_naxis"); /* first read input data for each tile */ for(n=0; n 0 */ if(halo > 0) { for(n=0; n 0) { dHold = (Data_holder *)malloc(nbound*sizeof(Data_holder)); for(l=0; l 0 */ if(halo > 0) { for(n=0; n 0) { dHold = (Data_holder *)malloc(nbound*sizeof(Data_holder)); for(l=0; lvar[varid].ndim; if(ndim < 2) mpp_error("fregrid_util(write_field_data): ndim must be no less than 2"); nwrite = (size_t *)malloc(ndim*sizeof(size_t)); start = (size_t *)malloc(ndim*sizeof(size_t)); for(i=0; ivar[varid].has_taxis) start[pos++] = level_t; if(field->var[varid].has_naxis) start[pos++] = level_n; if(field->var[varid].has_zaxis) start[pos++] = level_z; if(ndim != pos + 2) mpp_error("fregrid_util(write_field_data): mimstch between ndim and has_taxis/has_zaxis/has_naxis"); for(n=0; n 0) { bound[n].is1 = (int *)malloc(nbound*sizeof(int)); bound[n].ie1 = (int *)malloc(nbound*sizeof(int)); bound[n].js1 = (int *)malloc(nbound*sizeof(int)); bound[n].je1 = (int *)malloc(nbound*sizeof(int)); bound[n].is2 = (int *)malloc(nbound*sizeof(int)); bound[n].ie2 = (int *)malloc(nbound*sizeof(int)); bound[n].js2 = (int *)malloc(nbound*sizeof(int)); bound[n].je2 = (int *)malloc(nbound*sizeof(int)); bound[n].rotate = (int *)malloc(nbound*sizeof(int)); bound[n].tile2 = (int *)malloc(nbound*sizeof(int)); nb = 0; for(l=0; l<2*ncontacts; l++) { if(tile[l] != n) continue; switch(dir[l]) { case WEST: bound[n].is1[nb] = 0; bound[n].ie1[nb] = halo-1; bound[n].js1[nb] = min(jstart[l],jend[l])+halo; bound[n].je1[nb] = max(jstart[l],jend[l])+halo+shift; break; case EAST: bound[n].is1[nb] = nx+shift+halo; bound[n].ie1[nb] = nx+shift+halo+halo-1; bound[n].js1[nb] = min(jstart[l],jend[l])+halo; bound[n].je1[nb] = max(jstart[l],jend[l])+halo+shift; break; case SOUTH: bound[n].is1[nb] = min(istart[l],iend[l])+halo; bound[n].ie1[nb] = max(istart[l],iend[l])+halo+shift; bound[n].js1[nb] = 0; bound[n].je1[nb] = halo-1; break; case NORTH: bound[n].is1[nb] = min(istart[l],iend[l])+halo; bound[n].ie1[nb] = max(istart[l],iend[l])+halo+shift; bound[n].js1[nb] = ny+shift+halo; bound[n].je1[nb] = ny+shift+halo+halo-1; break; } l2 = (l+ncontacts)%(2*ncontacts); bound[n].tile2[nb] = tile[l2]; switch(dir[l2]) { case WEST: bound[n].is2[nb] = halo+shift; bound[n].ie2[nb] = halo+shift+halo-1; bound[n].js2[nb] = min(jstart[l2],jend[l2])+halo; bound[n].je2[nb] = max(jstart[l2],jend[l2])+halo+shift; break; case EAST: bound[n].is2[nb] = nx-halo+1; bound[n].ie2[nb] = nx; bound[n].js2[nb] = min(jstart[l2],jend[l2])+halo; bound[n].je2[nb] = max(jstart[l2],jend[l2])+halo+shift; break; case SOUTH: bound[n].is2[nb] = min(istart[l2],iend[l2])+halo; bound[n].ie2[nb] = max(istart[l2],iend[l2])+halo+shift; bound[n].js2[nb] = halo+shift; bound[n].je2[nb] = halo+shift+halo-1; break; case NORTH: bound[n].is2[nb] = min(istart[l2],iend[l2])+halo; bound[n].ie2[nb] = max(istart[l2],iend[l2])+halo+shift; bound[n].js2[nb] = ny-halo+1; bound[n].je2[nb] = ny; break; } bound[n].rotate[nb] = ZERO; if(dir[l] == WEST && dir[l2] == NORTH) bound[n].rotate[nb] = NINETY; if(dir[l] == EAST && dir[l2] == SOUTH) bound[n].rotate[nb]= NINETY; if(dir[l] == SOUTH && dir[l2] == EAST) bound[n].rotate[nb] = MINUS_NINETY; if(dir[l] == NORTH && dir[l2] == WEST) bound[n].rotate[nb] = MINUS_NINETY; if(dir[l] == NORTH && dir[l2] == NORTH) bound[n].rotate[nb] = ONE_HUNDRED_EIGHTY; /* make sure the size match at the boundary */ if( (bound[n].ie2[nb]-bound[n].is2[nb]+1)*(bound[n].je2[nb]-bound[n].js2[nb]+1) != (bound[n].ie1[nb]-bound[n].is1[nb]+1)*(bound[n].je1[nb]-bound[n].js1[nb]+1) ) mpp_error("fregrid_util: size mismatch between the boundary"); nb++; } } } }; /* setup_boundary */ void delete_bound_memory(int ntiles, Bound_config *bound) { int n; for(n=0; n 0) { free(bound[n].is1); free(bound[n].ie1); free(bound[n].js1); free(bound[n].je1); free(bound[n].is2); free(bound[n].ie2); free(bound[n].js2); free(bound[n].je2); free(bound[n].tile2); free(bound[n].rotate); } } } /*----------------------------------------------------------------------------- void init_halo(double *var, int nx, int ny, int nz, int halo) initialze the halo data to be zero. ---------------------------------------------------------------------------*/ void init_halo(double *var, int nx, int ny, int nz, int halo) { int i, j, k; int nxd, nyd, nall; nxd = nx+2*halo; nyd = ny+2*halo; nall = nxd*nyd; for(k=0; knbound; size1 = nx*ny; for(n=0; nis1[n]; ie1 = bound->ie1[n]; js1 = bound->js1[n]; je1 = bound->je1[n]; is2 = bound->is2[n]; ie2 = bound->ie2[n]; js2 = bound->js2[n]; je2 = bound->je2[n]; nx2 = dHold[n].nx; ny2 = dHold[n].ny; size2 = nx2*ny2; bufsize = nz*(ie2-is2+1)*(je2-js2+1); buffer = (double *)malloc(bufsize*sizeof(double)); /* fill the buffer */ l = 0; switch(bound->rotate[n]) { case ZERO: for(k=0; k=is2; i--) for(j=js2; j<=je2; j++) buffer[l++] = dHold[n].data[k*size2+j*nx2+i]; break; case MINUS_NINETY: for(k=0; k=js2; j--) buffer[l++] = dHold[n].data[k*size2+j*nx2+i]; break; case ONE_HUNDRED_EIGHTY: for(k=0; k=js2; j--) for(i=ie2; i>=is2; i--) buffer[l++] = dHold[n].data[k*size2+j*nx2+i]; break; } l = 0; for(k=0; k