/*------------------------------------------------------------------------------ void conserve_interp() conservative interpolation through exchange grid. Currently only first order interpolation are implemented here. ----------------------------------------------------------------------------*/ void conserve_interp(int nx_src, int ny_src, int nx_dst, int ny_dst, const double *x_src, const double *y_src, const double *x_dst, const double *y_dst, const double *mask_src, const double *data_src, double *data_dst ) { int n, nxgrid; int *xgrid_i1, *xgrid_j1, *xgrid_i2, *xgrid_j2; double *xgrid_area, *dst_area, *area_frac; /* get the exchange grid between source and destination grid. */ xgrid_i1 = (int *)malloc(MAXXGRID*sizeof(int)); xgrid_j1 = (int *)malloc(MAXXGRID*sizeof(int)); xgrid_i2 = (int *)malloc(MAXXGRID*sizeof(int)); xgrid_j2 = (int *)malloc(MAXXGRID*sizeof(int)); xgrid_area = (double *)malloc(MAXXGRID*sizeof(double)); dst_area = (double *)malloc(nx_dst*ny_dst*sizeof(double)); nxgrid = create_xgrid_2dx2d_order1(&nx_src, &ny_src, &nx_dst, &ny_dst, x_src, y_src, x_dst, y_dst, mask_src, xgrid_i1, xgrid_j1, xgrid_i2, xgrid_j2, xgrid_area ); get_grid_area(&nx_dst, &ny_dst, x_dst, y_dst, dst_area); area_frac = (double *)malloc(nxgrid*sizeof(double)); for(n=0; n<nxgrid; n++) area_frac[n] = xgrid_area[n]/dst_area[xgrid_j2[n]*nx_dst+xgrid_i2[n]]; for(n=0; n<nx_dst*ny_dst; n++) { data_dst[n] = 0; } for(n=0; n<nxgrid; n++) { data_dst[xgrid_j2[n]*nx_dst+xgrid_i2[n]] += data_src[xgrid_j1[n]*nx_src+xgrid_i1[n]]*area_frac[n]; } free(xgrid_i1); free(xgrid_j1); free(xgrid_i2); free(xgrid_j2); free(xgrid_area); free(dst_area); free(area_frac); }; /* conserve_interp */
/******************************************************************************* void do_scalar_conserve_interp( ) doing conservative interpolation *******************************************************************************/ void do_scalar_conserve_interp(Interp_config *interp, int varid, int ntiles_in, const Grid_config *grid_in, int ntiles_out, const Grid_config *grid_out, const Field_config *field_in, Field_config *field_out, unsigned int opcode) { int nx1, ny1, nx2, ny2, i1, j1, i2, j2, tile, n, m, i, j, n1, n2; int has_missing, halo, interp_method; double area, missing, di, dj; double *out_area; interp_method = field_in->var[varid].interp_method; halo = 0; if(interp_method == CONSERVE_ORDER2) halo = 1; missing = field_in->var[varid].missing; has_missing = field_in->var[varid].has_missing; for(m=0; m<ntiles_out; m++) { nx2 = grid_out[m].nxc; ny2 = grid_out[m].nyc; out_area = (double *)malloc(nx2*ny2*sizeof(double)); for(i=0; i<nx2*ny2; i++) field_out[m].data[i] = 0.0; for(i=0; i<nx2*ny2; i++) out_area[i] = 0.0; if(interp_method == CONSERVE_ORDER1) { if(has_missing) { for(n=0; n<interp[m].nxgrid; n++) { i2 = interp[m].i_out[n]; j2 = interp[m].j_out[n]; i1 = interp[m].i_in [n]; j1 = interp[m].j_in [n]; tile = interp[m].t_in [n]; area = interp[m].area [n]; nx1 = grid_in[tile].nx; ny1 = grid_in[tile].ny; if( field_in[tile].data[j1*nx1+i1] != missing ) { field_out[m].data[j2*nx2+i2] += field_in[tile].data[j1*nx1+i1]*area; out_area[j2*nx2+i2] += area; } } } else { for(n=0; n<interp[m].nxgrid; n++) { i2 = interp[m].i_out[n]; j2 = interp[m].j_out[n]; i1 = interp[m].i_in [n]; j1 = interp[m].j_in [n]; tile = interp[m].t_in [n]; area = interp[m].area [n]; nx1 = grid_in[tile].nx; ny1 = grid_in[tile].ny; field_out[m].data[j2*nx2+i2] += field_in[tile].data[j1*nx1+i1]*area; out_area[j2*nx2+i2] += area; } } } else { if(has_missing) { for(n=0; n<interp[m].nxgrid; n++) { i2 = interp[m].i_out[n]; j2 = interp[m].j_out[n]; i1 = interp[m].i_in [n]; j1 = interp[m].j_in [n]; di = interp[m].di_in[n]; dj = interp[m].dj_in[n]; tile = interp[m].t_in [n]; area = interp[m].area [n]; nx1 = grid_in[tile].nx; ny1 = grid_in[tile].ny; n2 = (j1+1)*(nx1+2)+i1+1; if( field_in[tile].data[n2] != missing ) { n1 = j1*nx1+i1; if(field_in[tile].grad_mask[n1]) { /* use zero gradient */ field_out[m].data[j2*nx2+i2] += field_in[tile].data[n2]*area; } else { field_out[m].data[j2*nx2+i2] += (field_in[tile].data[n2]+field_in[tile].grad_x[n1]*di +field_in[tile].grad_y[n1]*dj)*area; } out_area[j2*nx2+i2] += area; } } } else { for(n=0; n<interp[m].nxgrid; n++) { i2 = interp[m].i_out[n]; j2 = interp[m].j_out[n]; i1 = interp[m].i_in [n]; j1 = interp[m].j_in [n]; di = interp[m].di_in[n]; dj = interp[m].dj_in[n]; tile = interp[m].t_in [n]; area = interp[m].area [n]; nx1 = grid_in[tile].nx; ny1 = grid_in[tile].ny; n1 = j1*nx1+i1; n2 = (j1+1)*(nx1+2)+i1+1; field_out[m].data[j2*nx2+i2] += (field_in[tile].data[n2]+field_in[tile].grad_x[n1]*di +field_in[tile].grad_y[n1]*dj)*area; out_area[j2*nx2+i2] += area; } } } if(opcode & TARGET) { for(i=0; i<nx2*ny2; i++) { if(out_area[i] > 0) field_out[m].data[i] /= grid_out[m].area[i]; else field_out[m].data[i] = missing; } } else { for(i=0; i<nx2*ny2; i++) { if(out_area[i] > 0) field_out[m].data[i] /= out_area[i]; else field_out[m].data[i] = missing; } } } free(out_area); /* conservation check if needed */ if(opcode & CHECK_CONSERVE) { double gsum_in, gsum_out, dd; double *area; gsum_in = 0; gsum_out = 0; for(n=0; n<ntiles_in; n++) { nx1 = grid_in[n].nx; ny1 = grid_in[n].ny; area = (double *)malloc(nx1*ny1*sizeof(double)); get_grid_area(&nx1, &ny1, grid_in[n].lonc, grid_in[n].latc, area); for(j=0; j<ny1; j++) for(i=0; i<nx1; i++) { dd = field_in[n].data[(j+halo)*(nx1+2*halo)+i+halo]; if(dd != missing) gsum_in += dd*area[j*nx1+i]; } free(area); } for(n=0; n<ntiles_out; n++) { nx2 = grid_out[n].nxc; ny2 = grid_out[n].nyc; area = (double *)malloc(nx2*ny2*sizeof(double)); get_grid_area(&nx2, &ny2, grid_out[n].lonc, grid_out[n].latc, area); for(j=0; j<ny2; j++) for(i=0; i<nx2; i++) { dd = field_out[n].data[j*nx2+i]; if(dd != missing) gsum_out += dd*area[j*nx2+i]; } free(area); } mpp_sum_double(1, &gsum_out); if(mpp_pe() == mpp_root_pe()) printf("the flux(data*area) sum of %s: input = %g, output = %g, diff = %g. \n", field_in->var[varid].name, gsum_in, gsum_out, gsum_out-gsum_in); } }; /* do_scalar_conserve_interp */
int main (int argc, char *argv[]) { int c, n, i; int errflg = (argc == 1); int option_index = 0; int fid, vid, nfile_aXl, ntiles; int *nx, *ny; double **lonb, **latb, **land_area, **ocean_area, **cell_area; char **axl_file = NULL, **axo_file=NULL, **lxo_file=NULL; char **ocn_topog_file = NULL; char *input_mosaic = NULL; char mosaic_name[STRING] = "mosaic", mosaic_file[STRING]; char griddir[STRING], lnd_mosaic[STRING], filepath[STRING]; char history[512]; static struct option long_options[] = { {"input_mosaic", required_argument, NULL, 'i'}, {"mosaic_name", required_argument, NULL, 'm'}, {NULL, 0, NULL, 0} }; /* * process command line */ while ((c = getopt_long(argc, argv, "i:", long_options, &option_index) ) != -1) switch (c) { case 'i': input_mosaic = optarg; break; case 'm': strcpy(mosaic_name,optarg); break; case '?': errflg++; } if (errflg || !input_mosaic) { char **u = usage; while (*u) { fprintf(stderr, "%s\n", *u); u++; } exit(2); } strcpy(history,argv[0]); for(i=1;i<argc;i++) { strcat(history, " "); strcat(history, argv[i]); } /* First get land grid information */ mpp_init(&argc, &argv); sprintf(mosaic_file, "%s.nc", mosaic_name); get_file_path(input_mosaic, griddir); fid = mpp_open(input_mosaic, MPP_READ); vid = mpp_get_varid(fid, "lnd_mosaic_file"); mpp_get_var_value(fid, vid, lnd_mosaic); nfile_aXl = mpp_get_dimlen( fid, "nfile_aXl"); /*make sure the directory that stores the mosaic_file is not current directory */ { char cur_path[STRING]; if(getcwd(cur_path, STRING) != cur_path ) mpp_error("make_quick_mosaic: The size of cur_path maybe is not big enough"); printf("The current directory is %s\n", cur_path); printf("The mosaic file location is %s\n", griddir); if(strcmp(griddir, cur_path)==0 || strcmp( griddir, ".")==0) mpp_error("make_quick_mosaic: The input mosaic file location should not be current directory"); } sprintf(filepath, "%s/%s", griddir, lnd_mosaic); ntiles = read_mosaic_ntiles(filepath); /* copy the lnd_mosaic file and grid file */ { int fid2, vid2; char cmd[STRING], gridfile[STRING]; size_t start[4], nread[4]; sprintf(cmd, "cp %s %s", filepath, lnd_mosaic); system(cmd); fid2 = mpp_open(filepath, MPP_READ); vid2 = mpp_get_varid(fid2, "gridfiles"); for(i=0; i<4; i++) { start[i] = 0; nread[i] = 1; } for(n=0; n<ntiles; n++) { start[0] = n; nread[1] = STRING; mpp_get_var_value_block(fid2, vid2, start, nread, gridfile); sprintf(cmd, "cp %s/%s %s", griddir, gridfile, gridfile); printf("%s \n", cmd); system(cmd); } mpp_close(fid2); } /* ntiles should be either 1 or ntiles = nfile_aXl */ if(ntiles != nfile_aXl && ntiles != 1) mpp_error("make_quick_mosaic: only support ntiles = 1 or ntiles = nfile_aXl, contact developer"); nx = (int *)malloc(ntiles*sizeof(int)); ny = (int *)malloc(ntiles*sizeof(int)); read_mosaic_grid_sizes(filepath, nx, ny); lonb = (double **)malloc(ntiles*sizeof(double *)); latb = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { lonb[n] = (double *)malloc((nx[n]+1)*(ny[n]+1)*sizeof(double)); latb[n] = (double *)malloc((nx[n]+1)*(ny[n]+1)*sizeof(double)); read_mosaic_grid_data(filepath, "x", nx[n], ny[n], lonb[n], n, 0, 0); read_mosaic_grid_data(filepath, "y", nx[n], ny[n], latb[n], n, 0, 0); for(i=0; i<(nx[n]+1)*(ny[n]+1); i++) { lonb[n][i] *= (M_PI/180.0); latb[n][i] *= (M_PI/180.0); } } /* read the exchange grid information and get the land/sea mask of land model*/ land_area = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { land_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double)); for(i=0; i<nx[n]*ny[n]; i++) land_area[n][i] = 0; } vid = mpp_get_varid(fid, "aXl_file"); for(n=0; n<nfile_aXl; n++) { size_t start[4], nread[4]; int nxgrid; char aXl_file[STRING]; start[0] = n; start[1] = 0; nread[0] = 1; nread[1] = STRING; mpp_get_var_value_block(fid, vid, start, nread, aXl_file); sprintf(filepath, "%s/%s", griddir, aXl_file); nxgrid = read_mosaic_xgrid_size(filepath); if(nxgrid>0) { int l; int *i1, *j1, *i2, *j2; double *area; i1 = (int *)malloc(nxgrid*sizeof(int)); j1 = (int *)malloc(nxgrid*sizeof(int)); i2 = (int *)malloc(nxgrid*sizeof(int)); j2 = (int *)malloc(nxgrid*sizeof(int)); area = (double *)malloc(nxgrid*sizeof(double)); read_mosaic_xgrid_order1(filepath, i1, j1, i2, j2, area); if(ntiles == 1) { for(l=0; l<nxgrid; l++) land_area[0][j2[l]*nx[0]+i2[l]] += (area[l]*4*M_PI*RADIUS*RADIUS); } else { for(l=0; l<nxgrid; l++) land_area[n][j2[l]*nx[n]+i2[l]] += (area[l]*4*M_PI*RADIUS*RADIUS); } free(i1); free(j1); free(i2); free(j2); free(area); } } mpp_close(fid); /* calculate ocean area */ ocean_area = (double **)malloc(ntiles*sizeof(double *)); cell_area = (double **)malloc(ntiles*sizeof(double *)); for(n=0; n<ntiles; n++) { ocean_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double)); cell_area[n] = (double *)malloc(nx[n]*ny[n]*sizeof(double)); get_grid_area(&nx[n], &ny[n], lonb[n], latb[n], cell_area[n]); for(i=0; i<nx[n]*ny[n]; i++) { ocean_area[n][i] = cell_area[n][i]; if( fabs(ocean_area[n][i]-land_area[n][i])/ocean_area[n][i] < AREA_RATIO_THRESH ) ocean_area[n][i] = 0; else ocean_area[n][i] -= land_area[n][i]; if(ocean_area[n][i] < 0) { printf("at i = %d, ocean_area = %g, land_area = %g, cell_area=%g\n", i, ocean_area[n][i], land_area[n][i], cell_area[n][i]); mpp_error("make_quick_mosaic: ocean area is negative at some points"); } } } /* write out land mask */ { for(n=0; n<ntiles; n++) { int fid, id_mask, dims[2]; char lnd_mask_file[STRING]; double *mask; mask = (double *)malloc(nx[n]*ny[n]*sizeof(double)); for(i=0; i<nx[n]*ny[n]; i++) mask[i] = land_area[n][i]/cell_area[n][i]; if(ntiles > 1) sprintf(lnd_mask_file, "land_mask_tile%d.nc", n+1); else strcpy(lnd_mask_file, "land_mask.nc"); fid = mpp_open(lnd_mask_file, MPP_WRITE); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dims[1] = mpp_def_dim(fid, "nx", nx[n]); dims[0] = mpp_def_dim(fid, "ny", ny[n]); id_mask = mpp_def_var(fid, "mask", MPP_DOUBLE, 2, dims, 2, "standard_name", "land fraction at T-cell centers", "units", "none"); mpp_end_def(fid); mpp_put_var_value(fid, id_mask, mask); free(mask); mpp_close(fid); } } /* write out ocean mask */ { for(n=0; n<ntiles; n++) { int fid, id_mask, dims[2]; char ocn_mask_file[STRING]; double *mask; mask = (double *)malloc(nx[n]*ny[n]*sizeof(double)); for(i=0; i<nx[n]*ny[n]; i++) mask[i] = ocean_area[n][i]/cell_area[n][i]; if(ntiles > 1) sprintf(ocn_mask_file, "ocean_mask_tile%d.nc", n+1); else strcpy(ocn_mask_file, "ocean_mask.nc"); fid = mpp_open(ocn_mask_file, MPP_WRITE); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dims[1] = mpp_def_dim(fid, "nx", nx[n]); dims[0] = mpp_def_dim(fid, "ny", ny[n]); id_mask = mpp_def_var(fid, "mask", MPP_DOUBLE, 2, dims, 2, "standard_name", "ocean fraction at T-cell centers", "units", "none"); mpp_end_def(fid); mpp_put_var_value(fid, id_mask, mask); free(mask); mpp_close(fid); } } ocn_topog_file = (char **)malloc(ntiles*sizeof(char *)); axl_file = (char **)malloc(ntiles*sizeof(char *)); axo_file = (char **)malloc(ntiles*sizeof(char *)); lxo_file = (char **)malloc(ntiles*sizeof(char *)); for(n=0; n<ntiles; n++) { axl_file[n] = (char *)malloc(STRING*sizeof(char)); axo_file[n] = (char *)malloc(STRING*sizeof(char)); lxo_file[n] = (char *)malloc(STRING*sizeof(char)); ocn_topog_file[n] = (char *)malloc(STRING*sizeof(char)); sprintf(ocn_topog_file[n], "ocean_topog_tile%d.nc", n+1); sprintf(axl_file[n], "atmos_mosaic_tile%dXland_mosaic_tile%d.nc", n+1, n+1); sprintf(axo_file[n], "atmos_mosaic_tile%dXocean_mosaic_tile%d.nc", n+1, n+1); sprintf(lxo_file[n], "land_mosaic_tile%dXocean_mosaic_tile%d.nc", n+1, n+1); } for(n=0; n<ntiles; n++) { int *i1, *j1, *i2, *j2; double *area, *di, *dj; int nxgrid, i, j; int fid, dim_string, dim_ncells, dim_two, dims[2]; int id_contact, id_tile1_cell, id_tile2_cell; int id_xgrid_area, id_tile1_dist, id_tile2_dist; size_t start[4], nwrite[4]; char contact[STRING]; for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } /* first calculate the atmXlnd exchange grid */ i1 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); j1 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); i2 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); j2 = (int *)malloc(nx[n]*ny[n]*sizeof(int)); area = (double *)malloc(nx[n]*ny[n]*sizeof(double)); di = (double *)malloc(nx[n]*ny[n]*sizeof(double)); dj = (double *)malloc(nx[n]*ny[n]*sizeof(double)); /* write out the atmosXland exchange grid file, The file name will be atmos_mosaic_tile#Xland_mosaic_tile#.nc */ nxgrid = 0; for(j=0; j<ny[n]; j++) for(i=0; i<nx[n]; i++) { if(land_area[n][j*nx[n]+i] >0) { i1[nxgrid] = i+1; j1[nxgrid] = j+1; i2[nxgrid] = i+1; j2[nxgrid] = j+1; area[nxgrid] = land_area[n][j*nx[n]+i]; di[nxgrid] = 0; dj[nxgrid] = 0; nxgrid++; } } fid = mpp_open(axl_file[n], MPP_WRITE); sprintf(contact, "atmos_mosaic:tile%d::land_mosaic:tile%d", n+1, n+1); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec", "contact_type", "exchange", "parent1_cell", "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance"); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid"); mpp_end_def(fid); nwrite[0] = strlen(contact); mpp_put_var_value_block(fid, id_contact, start, nwrite, contact); nwrite[0] = nxgrid; mpp_put_var_value(fid, id_xgrid_area, area); mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di); start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj); mpp_close(fid); /* write out the atmosXocean exchange grid file, The file name will be atmos_mosaic_tile#Xocean_mosaic_tile#.nc */ nxgrid = 0; for(j=0; j<ny[n]; j++) for(i=0; i<nx[n]; i++) { if(ocean_area[n][j*nx[n]+i] >0) { i1[nxgrid] = i+1; j1[nxgrid] = j+1; i2[nxgrid] = i+1; j2[nxgrid] = j+1; area[nxgrid] = ocean_area[n][j*nx[n]+i]; di[nxgrid] = 0; dj[nxgrid] = 0; nxgrid++; } } fid = mpp_open(axo_file[n], MPP_WRITE); sprintf(contact, "atmos_mosaic:tile%d::ocean_mosaic:tile%d", n+1, n+1); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec", "contact_type", "exchange", "parent1_cell", "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance"); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid"); mpp_end_def(fid); start[1] = 0; nwrite[0] = strlen(contact); mpp_put_var_value_block(fid, id_contact, start, nwrite, contact); nwrite[0] = nxgrid; mpp_put_var_value(fid, id_xgrid_area, area); mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di); start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj); mpp_close(fid); /* write out landXocean exchange grid information */ fid = mpp_open(lxo_file[n], MPP_WRITE); sprintf(contact, "land_mosaic:tile%d::ocean_mosaic:tile%d", n+1, n+1); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); id_contact = mpp_def_var(fid, "contact", MPP_CHAR, 1, &dim_string, 7, "standard_name", "grid_contact_spec", "contact_type", "exchange", "parent1_cell", "tile1_cell", "parent2_cell", "tile2_cell", "xgrid_area_field", "xgrid_area", "distant_to_parent1_centroid", "tile1_distance", "distant_to_parent2_centroid", "tile2_distance"); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1_cell = mpp_def_var(fid, "tile1_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", MPP_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", MPP_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); id_tile1_dist = mpp_def_var(fid, "tile1_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); id_tile2_dist = mpp_def_var(fid, "tile2_distance", MPP_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent2_cell_centroid"); mpp_end_def(fid); start[1] = 0; nwrite[0] = strlen(contact); mpp_put_var_value_block(fid, id_contact, start, nwrite, contact); nwrite[0] = nxgrid; mpp_put_var_value(fid, id_xgrid_area, area); mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, i1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, i2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, di); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, di); start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, j1); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, j2); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, dj); mpp_put_var_value_block(fid, id_tile2_dist, start, nwrite, dj); mpp_close(fid); free(i1); free(j1); free(i2); free(j2); free(area); free(di); free(dj); } /*Fianlly create the coupler mosaic file mosaic_name.nc */ { int dim_string, dim_axo, dim_axl, dim_lxo, dims[2]; int id_amosaic_file, id_lmosaic_file, id_omosaic_file, id_otopog_file; int id_axo_file, id_axl_file, id_lxo_file; size_t start[4], nwrite[4]; for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } printf("mosaic_file is %s\n", mosaic_file); fid = mpp_open(mosaic_file, MPP_WRITE); mpp_def_global_att(fid, "grid_version", grid_version); mpp_def_global_att(fid, "code_version", tagname); mpp_def_global_att(fid, "history", history); dim_string = mpp_def_dim(fid, "string", STRING); dim_axo = mpp_def_dim(fid, "nfile_aXo", ntiles); dim_axl = mpp_def_dim(fid, "nfile_aXl", ntiles); dim_lxo = mpp_def_dim(fid, "nfile_lXo", ntiles); id_amosaic_file = mpp_def_var(fid, "atm_mosaic_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "atmosphere_mosaic_file_name"); id_lmosaic_file = mpp_def_var(fid, "lnd_mosaic_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "land_mosaic_file_name"); id_omosaic_file = mpp_def_var(fid, "ocn_mosaic_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "ocean_mosaic_file_name"); id_otopog_file = mpp_def_var(fid, "ocn_topog_file", MPP_CHAR, 1, &dim_string, 1, "standard_name", "ocean_topog_file_name"); dims[0] = dim_axo; dims[1] = dim_string; id_axo_file = mpp_def_var(fid, "aXo_file", MPP_CHAR, 2, dims, 1, "standard_name", "atmXocn_exchange_grid_file"); dims[0] = dim_axl; dims[1] = dim_string; id_axl_file = mpp_def_var(fid, "aXl_file", MPP_CHAR, 2, dims, 1, "standard_name", "atmXlnd_exchange_grid_file"); dims[0] = dim_lxo; dims[1] = dim_string; id_lxo_file = mpp_def_var(fid, "lXo_file", MPP_CHAR, 2, dims, 1, "standard_name", "lndXocn_exchange_grid_file"); mpp_end_def(fid); nwrite[0] = strlen(lnd_mosaic); mpp_put_var_value_block(fid, id_lmosaic_file, start, nwrite, lnd_mosaic); mpp_put_var_value_block(fid, id_amosaic_file, start, nwrite, lnd_mosaic); mpp_put_var_value_block(fid, id_omosaic_file, start, nwrite, lnd_mosaic); for(n=0; n<ntiles; n++) { start[0] = n; nwrite[0] =1; nwrite[1] = strlen(ocn_topog_file[n]); mpp_put_var_value_block(fid, id_otopog_file, start, nwrite, ocn_topog_file[n]); nwrite[1] = strlen(axl_file[n]); mpp_put_var_value_block(fid, id_axl_file, start, nwrite, axl_file[n]); nwrite[1] = strlen(axo_file[n]); mpp_put_var_value_block(fid, id_axo_file, start, nwrite, axo_file[n]); nwrite[1] = strlen(lxo_file[n]); mpp_put_var_value_block(fid, id_lxo_file, start, nwrite, lxo_file[n]); } mpp_close(fid); } for(n=0; n<ntiles; n++) { free(axl_file[n]); free(axo_file[n]); free(lxo_file[n]); } free(axl_file); free(axo_file); free(lxo_file); printf("\n***** Congratulation! You have successfully run make_quick_mosaic\n"); mpp_end(); return 0; } /* main */
/******************************************************************************* void setup_conserve_interp Setup the interpolation weight for conservative interpolation *******************************************************************************/ void setup_conserve_interp(int ntiles_in, const Grid_config *grid_in, int ntiles_out, Grid_config *grid_out, Interp_config *interp, unsigned int opcode) { int n, m, i, ii, jj, nx_in, ny_in, nx_out, ny_out, tile; size_t nxgrid, nxgrid2, nxgrid_prev; int *i_in, *j_in, *i_out, *j_out; int *tmp_t_in, *tmp_i_in, *tmp_j_in, *tmp_i_out, *tmp_j_out; double *tmp_di_in, *tmp_dj_in; double *xgrid_area, *tmp_area, *xgrid_clon, *xgrid_clat; double garea; typedef struct{ double *area; double *clon; double *clat; } CellStruct; CellStruct *cell_in; i_in = (int *)malloc(MAXXGRID * sizeof(int )); j_in = (int *)malloc(MAXXGRID * sizeof(int )); i_out = (int *)malloc(MAXXGRID * sizeof(int )); j_out = (int *)malloc(MAXXGRID * sizeof(int )); xgrid_area = (double *)malloc(MAXXGRID * sizeof(double)); if(opcode & CONSERVE_ORDER2) { xgrid_clon = (double *)malloc(MAXXGRID * sizeof(double)); xgrid_clat = (double *)malloc(MAXXGRID * sizeof(double)); } garea = 4*M_PI*RADIUS*RADIUS; if( opcode & READ) { for(n=0; n<ntiles_out; n++) { if( interp[n].file_exist ) { /* reading from file */ int *t_in, *ind; int fid, vid; nxgrid = read_mosaic_xgrid_size(interp[n].remap_file); t_in = (int *)malloc(nxgrid*sizeof(int )); ind = (int *)malloc(nxgrid*sizeof(int )); if(opcode & CONSERVE_ORDER1) read_mosaic_xgrid_order1(interp[n].remap_file, i_in, j_in, i_out, j_out, xgrid_area); else read_mosaic_xgrid_order2(interp[n].remap_file, i_in, j_in, i_out, j_out, xgrid_area, xgrid_clon, xgrid_clat); /*--- rescale the xgrid area */ for(i=0; i<nxgrid; i++) xgrid_area[i] *= garea; fid = mpp_open(interp[n].remap_file, MPP_READ); vid = mpp_get_varid(fid, "tile1"); mpp_get_var_value(fid, vid, t_in); mpp_close(fid); /*distribute the exchange grid on each pe according to target grid index*/ interp[n].nxgrid = 0; for(i=0; i<nxgrid; i++) { if( i_out[i] <= grid_out[n].iec && i_out[i] >= grid_out[n].isc && j_out[i] <= grid_out[n].jec && j_out[i] >= grid_out[n].jsc ) ind[interp[n].nxgrid++] = i; } interp[n].i_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].j_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].i_out = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].j_out = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].area = (double *)malloc(interp[n].nxgrid*sizeof(double)); interp[n].t_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); for(i=0; i< interp[n].nxgrid; i++) { interp[n].i_in [i] = i_in [ind[i]]; interp[n].j_in [i] = j_in [ind[i]]; interp[n].t_in [i] = t_in [ind[i]] - 1; interp[n].i_out[i] = i_out[ind[i]] - grid_out[n].isc; interp[n].j_out[i] = j_out[ind[i]] - grid_out[n].jsc; interp[n].area [i] = xgrid_area[ind[i]]; } if(opcode & CONSERVE_ORDER2) { interp[n].di_in = (double *)malloc(interp[n].nxgrid*sizeof(double)); interp[n].dj_in = (double *)malloc(interp[n].nxgrid*sizeof(double)); for(i=0; i< interp[n].nxgrid; i++) { interp[n].di_in[i] = xgrid_clon[ind[i]]; interp[n].dj_in[i] = xgrid_clat[ind[i]]; } } free(t_in); free(ind); } } if(mpp_pe() == mpp_root_pe())printf("NOTE: Finish reading index and weight for conservative interpolation from file.\n"); } else { cell_in = (CellStruct *)malloc(ntiles_in * sizeof(CellStruct)); for(m=0; m<ntiles_in; m++) { nx_in = grid_in[m].nx; ny_in = grid_in[m].ny; cell_in[m].area = (double *)malloc(nx_in*ny_in*sizeof(double)); cell_in[m].clon = (double *)malloc(nx_in*ny_in*sizeof(double)); cell_in[m].clat = (double *)malloc(nx_in*ny_in*sizeof(double)); for(n=0; n<nx_in*ny_in; n++) { cell_in[m].area[n] = 0; cell_in[m].clon[n] = 0; cell_in[m].clat[n] = 0; } } for(n=0; n<ntiles_out; n++) { nx_out = grid_out[n].nxc; ny_out = grid_out[n].nyc; interp[n].nxgrid = 0; for(m=0; m<ntiles_in; m++) { double *mask; nx_in = grid_in[m].nx; ny_in = grid_in[m].ny; mask = (double *)malloc(nx_in*ny_in*sizeof(double)); for(i=0; i<nx_in*ny_in; i++) mask[i] = 1.0; if(opcode & CONSERVE_ORDER1) { nxgrid = create_xgrid_2dx2d_order1(&nx_in, &ny_in, &nx_out, &ny_out, grid_in[m].lonc, grid_in[m].latc, grid_out[n].lonc, grid_out[n].latc, mask, i_in, j_in, i_out, j_out, xgrid_area); } else if(opcode & CONSERVE_ORDER2) { int g_nxgrid; int *g_i_in, *g_j_in; double *g_area, *g_clon, *g_clat; nxgrid = create_xgrid_2dx2d_order2(&nx_in, &ny_in, &nx_out, &ny_out, grid_in[m].lonc, grid_in[m].latc, grid_out[n].lonc, grid_out[n].latc, mask, i_in, j_in, i_out, j_out, xgrid_area, xgrid_clon, xgrid_clat); /* For the purpose of bitiwise reproducing, the following operation is needed. */ g_nxgrid = nxgrid; mpp_sum_int(1, &g_nxgrid); if(g_nxgrid > 0) { g_i_in = (int *)malloc(g_nxgrid*sizeof(int )); g_j_in = (int *)malloc(g_nxgrid*sizeof(int )); g_area = (double *)malloc(g_nxgrid*sizeof(double)); g_clon = (double *)malloc(g_nxgrid*sizeof(double)); g_clat = (double *)malloc(g_nxgrid*sizeof(double)); mpp_gather_field_int (nxgrid, i_in, g_i_in); mpp_gather_field_int (nxgrid, j_in, g_j_in); mpp_gather_field_double(nxgrid, xgrid_area, g_area); mpp_gather_field_double(nxgrid, xgrid_clon, g_clon); mpp_gather_field_double(nxgrid, xgrid_clat, g_clat); for(i=0; i<g_nxgrid; i++) { ii = g_j_in[i]*nx_in+g_i_in[i]; cell_in[m].area[ii] += g_area[i]; cell_in[m].clon[ii] += g_clon[i]; cell_in[m].clat[ii] += g_clat[i]; } free(g_i_in); free(g_j_in); free(g_area); free(g_clon); free(g_clat); } } else mpp_error("conserve_interp: interp_method should be CONSERVE_ORDER1 or CONSERVE_ORDER2"); free(mask); if(nxgrid > 0) { nxgrid_prev = interp[n].nxgrid; interp[n].nxgrid += nxgrid; if(nxgrid_prev == 0 ) { interp[n].i_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].j_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].i_out = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].j_out = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].area = (double *)malloc(interp[n].nxgrid*sizeof(double)); interp[n].t_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); for(i=0; i<interp[n].nxgrid; i++) { interp[n].t_in [i] = m; interp[n].i_in [i] = i_in [i]; interp[n].j_in [i] = j_in [i]; interp[n].i_out[i] = i_out[i]; interp[n].j_out[i] = j_out[i]; interp[n].area[i] = xgrid_area[i]; } if(opcode & CONSERVE_ORDER2) { interp[n].di_in = (double *)malloc(interp[n].nxgrid*sizeof(double)); interp[n].dj_in = (double *)malloc(interp[n].nxgrid*sizeof(double)); for(i=0; i<interp[n].nxgrid; i++) { jj = j_in [i]*nx_in+i_in [i]; interp[n].di_in [i] = xgrid_clon[i]/xgrid_area[i]; interp[n].dj_in [i] = xgrid_clat[i]/xgrid_area[i]; } } } else { tmp_i_in = interp[n].i_in; tmp_j_in = interp[n].j_in; tmp_i_out = interp[n].i_out; tmp_j_out = interp[n].j_out; tmp_area = interp[n].area; tmp_t_in = interp[n].t_in; interp[n].i_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].j_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].i_out = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].j_out = (int *)malloc(interp[n].nxgrid*sizeof(int )); interp[n].area = (double *)malloc(interp[n].nxgrid*sizeof(double)); interp[n].t_in = (int *)malloc(interp[n].nxgrid*sizeof(int )); for(i=0; i<nxgrid_prev; i++) { interp[n].t_in [i] = tmp_t_in [i]; interp[n].i_in [i] = tmp_i_in [i]; interp[n].j_in [i] = tmp_j_in [i]; interp[n].i_out[i] = tmp_i_out[i]; interp[n].j_out[i] = tmp_j_out[i]; interp[n].area [i] = tmp_area [i]; } for(i=0; i<nxgrid; i++) { ii = i + nxgrid_prev; interp[n].t_in [ii] = m; interp[n].i_in [ii] = i_in [i]; interp[n].j_in [ii] = j_in [i]; interp[n].i_out[ii] = i_out[i]; interp[n].j_out[ii] = j_out[i]; interp[n].area [ii] = xgrid_area[i]; } if(opcode & CONSERVE_ORDER2) { tmp_di_in = interp[n].di_in; tmp_dj_in = interp[n].dj_in; interp[n].di_in = (double *)malloc(interp[n].nxgrid*sizeof(double)); interp[n].dj_in = (double *)malloc(interp[n].nxgrid*sizeof(double)); for(i=0; i<nxgrid_prev; i++) { interp[n].di_in [i] = tmp_di_in [i]; interp[n].dj_in [i] = tmp_dj_in [i]; } for(i=0; i<nxgrid; i++) { ii = i + nxgrid_prev; jj = j_in [i]*nx_in+i_in [i]; interp[n].di_in [ii] = xgrid_clon[i]/xgrid_area[i]; interp[n].dj_in [ii] = xgrid_clat[i]/xgrid_area[i]; } free(tmp_di_in); free(tmp_dj_in); } free(tmp_t_in); free(tmp_i_in); free(tmp_j_in); free(tmp_i_out); free(tmp_j_out); free(tmp_area); } } /* if(nxgrid>0) */ } } if(opcode & CONSERVE_ORDER2) { /* subtrack the grid_in clon and clat to get the distance between xgrid and grid_in */ for(n=0; n<ntiles_in; n++) { double *area_in; double x1_in[50], y1_in[50], lon_in_avg, clon, clat; int j, n0, n1, n2, n3, n1_in; /* calcualte cell area */ nx_in = grid_in[n].nx; ny_in = grid_in[n].ny; area_in = (double *)malloc(nx_in*ny_in*sizeof(double)); get_grid_area(&nx_in, &ny_in, grid_in[n].lonc, grid_in[n].latc, area_in); for(j=0; j<ny_in; j++) for(i=0; i<nx_in; i++) { ii = j*nx_in + i; if(cell_in[n].area[ii] > 0) { if( fabs(cell_in[n].area[ii]-area_in[ii])/area_in[ii] < AREA_RATIO ) { cell_in[n].clon[ii] /= cell_in[n].area[ii]; cell_in[n].clat[ii] /= cell_in[n].area[ii]; } else { n0 = j*(nx_in+1)+i; n1 = j*(nx_in+1)+i+1; n2 = (j+1)*(nx_in+1)+i+1; n3 = (j+1)*(nx_in+1)+i; x1_in[0] = grid_in[n].lonc[n0]; y1_in[0] = grid_in[n].latc[n0]; x1_in[1] = grid_in[n].lonc[n1]; y1_in[1] = grid_in[n].latc[n1]; x1_in[2] = grid_in[n].lonc[n2]; y1_in[2] = grid_in[n].latc[n2]; x1_in[3] = grid_in[n].lonc[n3]; y1_in[3] = grid_in[n].latc[n3]; n1_in = fix_lon(x1_in, y1_in, 4, M_PI); lon_in_avg = avgval_double(n1_in, x1_in); clon = poly_ctrlon(x1_in, y1_in, n1_in, lon_in_avg); clat = poly_ctrlat (x1_in, y1_in, n1_in ); cell_in[n].clon[ii] = clon/area_in[ii]; cell_in[n].clat[ii] = clat/area_in[ii]; } } } free(area_in); } for(n=0; n<ntiles_out; n++) { for(i=0; i<interp[n].nxgrid; i++) { tile = interp[n].t_in[i]; ii = interp[n].j_in[i] * grid_in[tile].nx + interp[n].i_in[i]; interp[n].di_in[i] -= cell_in[tile].clon[ii]; interp[n].dj_in[i] -= cell_in[tile].clat[ii]; } } /* free the memory */ for(n=0; n<ntiles_in; n++) { free(cell_in[n].area); free(cell_in[n].clon); free(cell_in[n].clat); } free(cell_in); } if( opcode & WRITE) { /* write out remapping information */ for(n=0; n<ntiles_out; n++) { int nxgrid; nxgrid = interp[n].nxgrid; mpp_sum_int(1, &nxgrid); if(nxgrid > 0) { size_t start[4], nwrite[4]; int fid, dim_string, dim_ncells, dim_two, dims[4]; int id_xgrid_area, id_tile1_dist; int id_tile1_cell, id_tile2_cell, id_tile1; int *gdata_int, *ldata_int; double *gdata_dbl; fid = mpp_open( interp[n].remap_file, MPP_WRITE); dim_string = mpp_def_dim(fid, "string", STRING); dim_ncells = mpp_def_dim(fid, "ncells", nxgrid); dim_two = mpp_def_dim(fid, "two", 2); dims[0] = dim_ncells; dims[1] = dim_two; id_tile1 = mpp_def_var(fid, "tile1", NC_INT, 1, &dim_ncells, 1, "standard_name", "tile_number_in_mosaic1"); id_tile1_cell = mpp_def_var(fid, "tile1_cell", NC_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic1"); id_tile2_cell = mpp_def_var(fid, "tile2_cell", NC_INT, 2, dims, 1, "standard_name", "parent_cell_indices_in_mosaic2"); id_xgrid_area = mpp_def_var(fid, "xgrid_area", NC_DOUBLE, 1, &dim_ncells, 2, "standard_name", "exchange_grid_area", "units", "m2"); if(opcode & CONSERVE_ORDER2) id_tile1_dist = mpp_def_var(fid, "tile1_distance", NC_DOUBLE, 2, dims, 1, "standard_name", "distance_from_parent1_cell_centroid"); mpp_end_def(fid); for(i=0; i<4; i++) { start[i] = 0; nwrite[i] = 1; } nwrite[0] = nxgrid; gdata_int = (int *)malloc(nxgrid*sizeof(int)); if(interp[n].nxgrid>0) ldata_int = (int *)malloc(interp[n].nxgrid*sizeof(int)); gdata_dbl = (double *)malloc(nxgrid*sizeof(double)); mpp_gather_field_double(interp[n].nxgrid, interp[n].area, gdata_dbl); mpp_put_var_value(fid, id_xgrid_area, gdata_dbl); mpp_gather_field_int(interp[n].nxgrid, interp[n].t_in, gdata_int); for(i=0; i<nxgrid; i++) gdata_int[i]++; mpp_put_var_value(fid, id_tile1, gdata_int); mpp_gather_field_int(interp[n].nxgrid, interp[n].i_in, gdata_int); for(i=0; i<nxgrid; i++) gdata_int[i]++; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, gdata_int); if(opcode & CONSERVE_ORDER2) { mpp_gather_field_double(interp[n].nxgrid, interp[n].di_in, gdata_dbl); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, gdata_dbl); } for(i=0; i<interp[n].nxgrid; i++) ldata_int[i] = interp[n].i_out[i] + grid_out[n].isc + 1; mpp_gather_field_int(interp[n].nxgrid, ldata_int, gdata_int); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, gdata_int); mpp_gather_field_int(interp[n].nxgrid, interp[n].j_in, gdata_int); for(i=0; i<nxgrid; i++) gdata_int[i]++; start[1] = 1; mpp_put_var_value_block(fid, id_tile1_cell, start, nwrite, gdata_int); if(opcode & CONSERVE_ORDER2) { mpp_gather_field_double(interp[n].nxgrid, interp[n].dj_in, gdata_dbl); mpp_put_var_value_block(fid, id_tile1_dist, start, nwrite, gdata_dbl); } for(i=0; i<interp[n].nxgrid; i++) ldata_int[i] = interp[n].j_out[i] + grid_out[n].jsc + 1; mpp_gather_field_int(interp[n].nxgrid, ldata_int, gdata_int); mpp_put_var_value_block(fid, id_tile2_cell, start, nwrite, gdata_int); free(gdata_int); free(gdata_dbl); if(interp[n].nxgrid>0)free(ldata_int); mpp_close(fid); } } } if(mpp_pe() == mpp_root_pe())printf("NOTE: done calculating index and weight for conservative interpolation\n"); } /* get target grid area if needed */ if( opcode & TARGET ) { for(n=0; n<ntiles_out; n++) { nx_out = grid_out[n].nxc; ny_out = grid_out[n].nyc; grid_out[n].area = (double *)malloc(nx_out*ny_out*sizeof(double)); get_grid_area(&nx_out,&ny_out, grid_out[n].lonc, grid_out[n].latc, grid_out[n].area); } } free(i_in); free(j_in); free(i_out); free(j_out); free(xgrid_area); if(opcode & CONSERVE_ORDER2) { free(xgrid_clon); free(xgrid_clat); } }; /* setup_conserve_interp */