#include #include #include #include #include #include "constant.h" #include "globals.h" #include "create_xgrid.h" #include "mosaic_util.h" #include "conserve_interp.h" #include "fregrid_util.h" #include "mpp.h" #include "mpp_io.h" #define AREA_RATIO (1.e-3) /******************************************************************************* 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= 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 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 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; i0) */ } } if(opcode & CONSERVE_ORDER2) { /* subtrack the grid_in clon and clat to get the distance between xgrid and grid_in */ for(n=0; n 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 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; i0)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; nvar[varid].missing; has_missing = field_in->var[varid].has_missing; nz = field_in->var[varid].nz; for(m=0; m 0) field_out[m].data[kk+i] /= grid_out[m].area[i]; else field_out[m].data[kk+i] = missing; } } else { for(i=0; i 0) field_out[m].data[kk+i] /= out_area[i]; else field_out[m].data[kk+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; nvar[varid].name, gsum_in, gsum_out, gsum_out-gsum_in); } }; /* do_scalar_conserve_interp */ /******************************************************************************* void do_vector_conserve_interp( ) doing conservative interpolation *******************************************************************************/ void do_vector_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 *u_in, const Field_config *v_in, Field_config *u_out, Field_config *v_out, unsigned int opcode) { int nx1, ny1, nx2, ny2, nz, i1, j1, i2, j2, tile, n, k, m, i, kk; double area, missing, tmp_x, tmp_y; double *out_area; nz = u_in->var[varid].nz; missing = u_in->var[varid].missing; /* first rotate input data */ for(n = 0; n < ntiles_in; n++) { if(grid_in[n].rotate) { nx1 = grid_in[n].nx; ny1 = grid_in[n].ny; for(k = 0; k < nz; k++) { for(i=0; i 0) { u_out[m].data[kk+i] /= grid_out[m].area[i]; v_out[m].data[kk+i] /= grid_out[m].area[i]; } else { u_out[m].data[kk+i] = missing; v_out[m].data[kk+i] = missing; } } } else { for(i=0; i 0) { u_out[m].data[kk+i] /= out_area[i]; v_out[m].data[kk+i] /= out_area[i]; } else { u_out[m].data[kk+i] = missing; v_out[m].data[kk+i] = missing; } } } /* rotate the data if needed */ if(grid_out[m].rotate) { for(i=0; i