void write_grid_file(void) { /* The following subroutine saves the depth, reduced gravity of */ /* each interface, the potential density of each layer, and the */ /* Coriolis parameter. A variety of metric terms are written to a */ /* separate file. */ char filename[40]; /* The file name of the save file. */ char filepath[120]; /* The path (dir/file) to the file. */ int i, j, cdfid, timeid; size_t err = 1; struct varcdfinfo varinfo[10]; /* vardesc is a structure defined in HIM_io.h. The elements of */ /* this structure, in order, are: (1) the variable name for the NetCDF*/ /* file; (2) the variable's long name; (3) a character indicating the */ /* horizontal grid, which may be '1' (column), 'h', 'q', 'u', or 'v', */ /* for the corresponding C-grid variable; (4) a character indicating */ /* the vertical grid, which may be 'L' (layer), 'i' (interface), */ /* '2' (mixed-layers), or '1' (no vertical location); (5) a character */ /* indicating the time levels of the field, which may be 's' (snap- */ /* shot), 'a' (average between snapshots), 'm' (monthly average), or */ /* '1' (no time variation); (6) the variable's units; and (7) a */ /* character indicating the size in memory to write, which may be */ /* 'd' (8-byte) or 'f' (4-byte). */ vardesc vars[4] = { {"D","Basin Depth",'h','1','1',"meter", 'd'}, {"g","Reduced gravity",'1','L','1',"meter second-2", 'd'}, {"R","Target Potential Density",'1','L','1',"kilogram meter-3", 'd'}, {"f","Coriolis Parameter",'q','1','1',"second-1", 'd'} }; sprintf(filename,"D.%d.%d.%d",NXTOT,NYTOT,NZ); strcpy(filepath, directory); strcat(filepath, filename); create_file(filepath, vars, 4, &cdfid, &timeid, varinfo); err *= write_field(cdfid, vars[0], varinfo[0], 0, D[0]); err *= write_field(cdfid, vars[1], varinfo[1], 0, g); err *= write_field(cdfid, vars[2], varinfo[2], 0, Rlay); err *= write_field(cdfid, vars[3], varinfo[3], 0, f[0]); close_file(&cdfid); if (err == 0) printf("Problems saving general parameters.\n"); { /* ### REVISIT THIS PART OF THE ROUTINE AFTER METRICS... ### */ double out[NYMEM][NXMEM]; /* An array for output. */ extern double hmask[NYMEM][NXMEM]; vardesc vars2[10]={ {"geolatb","latitude at q points",'q','1','1',"degree",'d'}, {"geolonb","longitude at q points",'q','1','1',"degree",'d'}, {"wet", "land or ocean?", 'h','1','1',"none",'d'}, {"geolat", "latitude at h points", 'h','1','1',"degree",'d'}, {"geolon","longitude at h points",'h','1','1',"degree",'d'}, {"dxh","Zonal grid spacing at h points",'h','1','1',"m",'d'}, {"dxq","Zonal grid spacing at q points",'q','1','1',"m",'d'}, {"dyh","Meridional grid spacing at h points",'h','1','1',"m",'d'}, {"dyq","Meridional grid spacing at q points",'q','1','1',"m",'d'}, {"Ah","Area of h cells",'h','1','1',"m2",'d'}, }; sprintf(filename,"grid.%d.%d",NXTOT,NYTOT); strcpy(filepath, directory); strcat(filepath, filename); create_file(filepath, vars2, 10, &cdfid, &timeid, varinfo); err *= write_field(cdfid, vars2[0], varinfo[0], 0, geolatq[0]); err *= write_field(cdfid, vars2[1], varinfo[1], 0, geolonq[0]); err *= write_field(cdfid, vars2[2], varinfo[2], 0, hmask[0]); err *= write_field(cdfid, vars2[3], varinfo[3], 0, geolath[0]); err *= write_field(cdfid, vars2[4], varinfo[4], 0, geolonh[0]); for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DXh(j,i); err *= write_field(cdfid, vars2[5], varinfo[5], 0, out[0]); for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DXq(j,i); err *= write_field(cdfid, vars2[6], varinfo[6], 0, out[0]); for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DYh(j,i); err *= write_field(cdfid, vars2[7], varinfo[7], 0, out[0]); for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DYq(j,i); err *= write_field(cdfid, vars2[8], varinfo[8], 0, out[0]); for (j=0;j<NYMEM;j++) for (i=0;i<NXMEM;i++) out[j][i]=DXDYh(j,i); err *= write_field(cdfid, vars2[9], varinfo[9], 0, out[0]); close_file(&cdfid); if (err == 0) printf("Problems saving latitude and longitude and wet.\n"); } }
void set_metrics(void) { int i,j; extern double areagr[NXMEM][NYMEM]; double Iareagr[NXMEM][NYMEM]; /* Calculate the values of the metric terms that might be used */ /* and save them in arrays. */ #ifdef CARTESIAN /* On a cartesian grid, the various DX... and DY... macros all */ /* point to the same scalars. */ i = 0; j = 0; DXh(i,j) = RE * LENLON * M_PI / (180.0 * NXTOT); DYh(i,j) = RE * LENLAT * M_PI / (180.0 * NYTOT); IDXh(i,j) = 1.0 / DXh(i,j); IDYh(i,j) = 1.0 / DYh(i,j); DXDYh(i,j) = DXh(i,j) * DYh(i,j); IDXDYh(i,j) = IDXh(i,j) * IDYh(i,j); for (j=Y0-1;j<=ny+2;j++) latq[j] = LOWLAT + LENLAT*(double)(j-Y0+Y0abs)/(double)NYTOT; for (j=Y0;j<=ny;j++) lath[j] = LOWLAT + LENLAT*((double)(j-Y0+Y0abs)-0.5)/(double)NYTOT; for (i=X0-1;i<=nx+2;i++) lonq[i] = WESTLON + LENLON*(double)(i-X0+X0abs)/(double)NXTOT; for (i=X0;i<=nx;i++) lonh[i] = WESTLON + LENLON*((double)(i-X0+X0abs)-0.5)/(double)NXTOT; # if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT) for (j=Y0;j<=NYTOT+Y0;j++) latq_tot[j] = LOWLAT + LENLAT*(double)(j-Y0)/(double)NYTOT; for (j=Y0;j<=NYTOT+Y0;j++) lath_tot[j] = LOWLAT + LENLAT*((double)(j-Y0)-0.5)/(double)NYTOT; # endif # if defined(PARALLEL_X) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT) for (i=X0;i<=NXTOT+X0;i++) lonq_tot[i] = WESTLON + LENLON*(double)(i-X0)/(double)NXTOT; for (i=X0;i<=NXTOT+X0;i++) lonh_tot[i] = WESTLON + LENLON*((double)(i-X0)-0.5)/(double)NXTOT; # endif #else /* All of the metric terms should be defined over the domain from */ /* X0-1 to nx+2. Outside of the physical domain, both the metrics */ /* and their inverses may be set to zero. */ /* Any points that are outside of the computational domain should */ /* have their values set to zero _BEFORE_ setting the other metric */ /* terms, because these macros may or may not expand to 2-dimensional */ /* arrays. */ /* The metric terms within the computational domain are set here. */ # ifdef ISOTROPIC { double C0, I_C0, yq, yh, jd; double fnRef, yRef; /* fnRef is the value of the integral of */ /* 1/(dx*cos(lat)) from the equator to a */ /* reference latitude, while yRef is the */ /* j-index of that reference latitude. */ int itt1, itt2; C0 = M_PI*((double) LENLON / (double) (180*NXTOT)); I_C0 = 1.0 / C0; /* With an isotropic grid, the north-south extent of the domain, */ /* the east-west extent, and the number of grid points in each */ /* direction are _not_ independent. Here the north-south extent */ /* will be determined to fit the east-west extent and the number of */ /* grid points. The grid is perfectly isotropic. */ # ifdef NORTHREFERENCE /* The following 2 lines fixes the refererence latitude at the */ /* northern edge of the domain, LOWLAT+LENLAT at j=NYTOT+Y0. */ yRef = Y0abs - Y0 - NYTOT; fnRef = I_C0 * INTSECY(((LOWLAT+LENLAT)*M_PI/180.0)); # else /* The following line sets the refererence latitude LOWLAT at j=Y0. */ yRef = Y0abs - Y0; fnRef = I_C0 * INTSECY((LOWLAT*M_PI/180.0)); # endif /* Everything else should pretty much work. */ yq = LOWLAT*M_PI/180.0; /* If the model is in parallel in the Y-direction, do the same set of */ /* calculations which would occur on a single processor. */ for (j=Y0-1-Y0abs;j<Y0-1;j++) { jd = fnRef + (double) (j + yRef) - 0.5; yh = find_root(jd,yq,&itt1); jd = fnRef + (double) (j + yRef); yq = find_root(jd,yh,&itt2); # if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT) latq_tot[j+Y0abs] = yq*180.0/M_PI; lath_tot[j+Y0abs] = yh*180.0/M_PI; # endif } for (j=Y0-1;j<=ny+2;j++) { jd = fnRef + (double) (j + yRef) - 0.5; yh = find_root(jd,yq,&itt1); jd = fnRef + (double) (j + yRef); yq = find_root(jd,yh,&itt2); latq[j] = yq*180.0/M_PI; lath[j] = yh*180.0/M_PI; # if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT) latq_tot[j+Y0abs] = yq*180.0/M_PI; lath_tot[j+Y0abs] = yh*180.0/M_PI; # endif for (i=X0-1;i<=nx+2;i++) { DXq(i,j) = cos(yq) * (RE * C0); DYq(i,j) = DXq(i,j); DXv(i,j) = DXq(i,j); DYv(i,j) = DYq(i,j); DXh(i,j) = cos(yh) * (RE * C0); DYh(i,j) = DXh(i,j); DXu(i,j) = DXh(i,j); DYu(i,j) = DYh(i,j); } } # if defined(PARALLEL_Y) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT) for (j=ny+3;j<=NYTOT+Y0-Y0abs;j++) { jd = fnRef + (double) (j + yRef) - 0.5; yh = find_root(jd,yq,&itt1); jd = fnRef + (double) (j + yRef); yq = find_root(jd,yh,&itt2); latq_tot[j+Y0abs] = yq*180.0/M_PI; lath_tot[j+Y0abs] = yh*180.0/M_PI; } # endif } for (i=X0-1;i<=nx+2;i++) lonq[i] = WESTLON + LENLON*(double)(i-X0+X0abs)/(double)NXTOT; for (i=X0;i<=nx;i++) lonh[i] = WESTLON + LENLON*((double)(i-X0+X0abs)-0.5)/(double)NXTOT; # if defined(PARALLEL_X) && !defined(PARALLEL_IO) && defined(NETCDF_OUTPUT) for (i=X0;i<=NXTOT+X0;i++) lonq_tot[i] = WESTLON + LENLON*(double)(i-X0)/(double)NXTOT; for (i=X0;i<=NXTOT+X0;i++) lonh_tot[i] = WESTLON + LENLON*((double)(i-X0)-0.5)/(double)NXTOT; # endif # else /* ISOTROPIC */ /* This code implements latitude/longitude coordinates on a sphere. */ //BX-a // for (j=0;j<=NYTOT-1;j++) { //HF for (j=Y0-1;j<=ny+2;j++) { for (j=2;j<NYTOT+2;j++) { latq[j] = qlat[j]; lath[j] = hlat[j]; } //BX-e /* HF for (i=0;i<=NXTOT-1;i++) { for (j=0;j<=NYTOT-1;j++) { DXq(i+2,j+2) = dxq[j][i]; DYq(i+2,j+2) = dyq[j][i]; DXv(i+2,j+2) = dxv[j][i]; DYv(i+2,j+2) = dyv[j][i]; DXh(i+2,j+2) = dxh[j][i]; DYh(i+2,j+2) = dyh[j][i]; DXu(i+2,j+2) = dxu[j][i]; DYu(i+2,j+2) = dyu[j][i]; } } */ //BX-a for (i=X0-1;i<=nx+2;i++) lonq[i] = WESTLON + LENLON*(double)(i-X0+X0abs)/(double)NXTOT; for (i=X0;i<=nx;i++) lonh[i] = WESTLON + LENLON*((double)(i-X0+X0abs)-0.5)/(double)NXTOT; //BX-e #endif /* The remaining code should not be changed. */ for (i=X0-1;i<=nx+2;i++) { for (j=Y0-1;j<=ny+2;j++) { IDXh(i,j) = (DXh(i,j) > 0.0) ? (1.0 / DXh(i,j)) : 0.0; IDXu(i,j) = (DXu(i,j) > 0.0) ? (1.0 / DXu(i,j)) : 0.0; IDXv(i,j) = (DXv(i,j) > 0.0) ? (1.0 / DXv(i,j)) : 0.0; IDXq(i,j) = (DXq(i,j) > 0.0) ? (1.0 / DXq(i,j)) : 0.0; IDYh(i,j) = (DYh(i,j) > 0.0) ? (1.0 / DYh(i,j)) : 0.0; IDYu(i,j) = (DYu(i,j) > 0.0) ? (1.0 / DYu(i,j)) : 0.0; IDYv(i,j) = (DYv(i,j) > 0.0) ? (1.0 / DYv(i,j)) : 0.0; IDYq(i,j) = (DYq(i,j) > 0.0) ? (1.0 / DYq(i,j)) : 0.0; //HF alternate def: DXDYh(i,j) = DXh(i,j) * DYh(i,j); //HF alternate def: IDXDYh(i,j) = IDXh(i,j) * IDYh(i,j); DXDYq(i,j) = DXq(i,j) * DYq(i,j); IDXDYq(i,j) = IDXq(i,j) * IDYq(i,j); Iareagr[i][j] = (areagr[i][j] > 0.0) ? (1.0 / areagr[i][j]) : 0.0; DXDYh(i,j) = areagr[i][j]; IDXDYh(i,j) = Iareagr[i][j]; } } #endif /* CARTESIAN */ }