3 # define GET_TERRAIN get_terrain
4 # define GET_LANDUSE get_landuse
7 # define GET_TERRAIN get_terrain__
8 # define GET_LANDUSE get_landuse__
10 # define GET_TERRAIN get_terrain_
11 # define GET_LANDUSE get_landuse_
21 int GET_TERRAIN ( float *adx
,
29 int *ipath
, int * ipathlen
) /* integer coded ASCII string from Funtran and len */
33 fprintf(stderr
, "***************************************************************\n" ) ;
34 fprintf(stderr
, "Access to RSMAS Topo Ingest Code is by Special Arrangement Only\n" ) ;
35 fprintf(stderr
, "in WRF. Please contact wrfhelp@ucar.edu. \n" ) ;
36 fprintf(stderr
, "***************************************************************\n" ) ;
41 int GET_LANDUSE ( float *adx
,
49 int *ipath
, int * ipathlen
) /* integer coded ASCII string from Funtran and len */
53 fprintf(stderr
, "***************************************************************\n" ) ;
54 fprintf(stderr
, "Access to RSMAS Topo Ingest Code is by Special Arrangement Only\n" ) ;
55 fprintf(stderr
, "in WRF. Please contact wrfhelp@ucar.edu. \n" ) ;
56 fprintf(stderr
, "***************************************************************\n" ) ;
63 # define _FILE_OFFSET_BITS 64
69 # include <rpc/types.h>
71 #elif (RPC_TYPES == 2)
72 # include <tirpc/rpc/types.h>
73 # include <tirpc/rpc/xdr.h>
79 # include <malloc/malloc.h>
83 #define MAXTOPOFILES 100
90 char fn
[MAXTOPOFILES
][MAXLEN
];
92 /* Grid spacings in km. */
93 float dx
[MAXTOPOFILES
];
95 /* Number of entries. */
99 static TsFileInfo tsfTopo
;
100 static TsFileInfo tsfOcean
;
101 static TsFileInfo tsfLU
;
103 static int tsFileInfo_initialized
= 0;
104 /* static float last_adx = 0.0 ; */
106 static char tsfTopo_fn
[MAXLEN
];
107 static char tsfLU_fn
[MAXLEN
];
108 static char tsfOcean_fn
[MAXLEN
];
112 static int numHeaderBytes
;
119 static int numTilesX
;
120 static int numTilesY
;
129 /* File information. */
135 if ( x
> 0.0 ) { return( (int)(x
+ 0.5) ) ; }
136 return((int)(x
- 0.5));
139 double aint(double x
)
142 return((double)(ix
));
145 double anint(double x
)
147 if (x
> 0.0) return((double)((int)(x
+ 0.5)));
148 return((double)((int)(x
- 0.5)));
151 static double normalizeAngle(double ang
)
172 static double lonDistNowrap(double lon1
, double lon2
)
174 double lon11
= normalizeAngle(lon1
);
175 double lon22
= normalizeAngle(lon2
);
176 if (lon22
< lon11
) lon22
+= 360.0;
177 return(fabs(lon22
- lon11
));
180 int tsLatLonToGridpoint(double lat
,
185 *ix
= lonDistNowrap(lon0
, lon
) / dlon
;
186 *iy
= (lat
- lat0
) / dlat
;
190 static int areEqual(double v1
, double v2
)
192 if (fabs(v1
-v2
) < 0.001) return(1);
196 static int setWrapAroundFlags(void)
198 /* Compute the end gridpoint location in x. */
199 double lon1
= lon0
+ dlon
*(globalNx
);
200 double lon2
= lon0
+ dlon
*(globalNx
-1);
201 double lat1
= lat0
+ dlat
*(globalNy
);
202 double lon0n
= normalizeAngle(lon0
);
203 double lon1n
= normalizeAngle(lon1
);
204 double lon2n
= normalizeAngle(lon2
);
207 if (areEqual(lon0n
, lon1n
))
209 /* Here the first and last indices in x are one grid interval
213 else if (areEqual(lon0n
, lon2n
))
215 /* Here the first and last indices in x are coincident. */
220 if (areEqual(lat0
, -90.0))
222 /* Here the first and last indices in x are one grid interval
226 if (areEqual(lat1
, 90.0))
228 /* Here the first and last indices in x are coincident. */
235 static int isMissing(float v
)
237 if (fabs(vmiss
- v
) < 0.1) return(1);
241 float tsGetValueInt(int aix
, int aiy
)
248 /* Perform bounds checking. */
253 else if (iy
> globalNy
- 1)
262 int n
= -(aix
- (globalNx
- 1)) / globalNx
;
267 int nx
= globalNx
- 1;
268 int n
= -(aix
- (nx
- 1)) / nx
;
281 int n
= aix
/ globalNx
;
286 int nx
= globalNx
- 1;
296 int tx
= ix
/ tileNx
;
297 int ty
= iy
/ tileNy
;
298 int tn
= tx
+ ty
*numTilesX
;
299 int txg
= ix
- tx
*tileNx
;
300 int tyg
= iy
- ty
*tileNy
;
301 int gn
= txg
+ tyg
*tileNx
;
303 long long ll_gn
= gn
;
304 long long ll_numHeaderBytes
= numHeaderBytes
;
305 long long ll_tileNx
= tileNx
;
306 long long ll_tileNy
= tileNy
;
309 /* This is used on machines that support fseeko64. Tested for in ./configure script */
310 long long loc
= ll_numHeaderBytes
+ ll_tileNx
*ll_tileNy
*sizeof(float)*tn
+
313 /* Seek to the proper location in the file and get the data value. */
314 fseeko64(fp
, loc
, SEEK_SET
);
317 /* This is used on machines that support _FILE_OFFSET_BITS=64 which makes
318 off_t be 64 bits, and for which fseeko can handle 64 bit offsets. This
319 is tested in the ./configure script */
320 off_t loc
= ll_numHeaderBytes
+ ll_tileNx
*ll_tileNy
*sizeof(float)*tn
+
323 fseeko(fp
, loc
, SEEK_SET
);
325 /* Note, this will not work correctly for very high resolution terrain input
326 because the offset is only 32 bits. */
327 off_t loc
= ll_numHeaderBytes
+ ll_tileNx
*ll_tileNy
*sizeof(float)*tn
+
330 fseek(fp
, loc
, SEEK_SET
);
333 xdr_float(xdrs
, (float *) &f
);
338 float tsGetValue(double ix
, double iy
)
340 int i0
= (int)(floor(ix
));
341 int j0
= (int)(floor(iy
));
342 int i1
= (int)(ceil(ix
));
343 int j1
= (int)(ceil(iy
));
345 /* Interpolate linearly to (oiloc, ojloc). */
346 float v0
= tsGetValueInt(i0
,j0
);
347 float v1
= tsGetValueInt(i0
,j1
);
348 float v2
= tsGetValueInt(i1
,j0
);
349 float v3
= tsGetValueInt(i1
,j1
);
351 if (isMissing(v0
)) return(vmiss
);
352 if (isMissing(v1
)) return(vmiss
);
353 if (isMissing(v2
)) return(vmiss
);
354 if (isMissing(v3
)) return(vmiss
);
359 float v4
= v2
*w0
+ v0
*(1.0-w0
);
360 float v5
= v3
*w0
+ v1
*(1.0-w0
);
361 float v6
= w1
*v5
+ (1.0-w1
)*v4
;
367 float tsGetValueLatLon(double lat
, double lon
)
370 tsLatLonToGridpoint(lat
,lon
,&ix
,&iy
);
371 return(tsGetValue(ix
,iy
));
374 int tsCloseTileSet(void)
392 int tsInitTileSet(char *fn
)
394 vmiss
= -100000000.00;
400 fprintf(stderr
,"Open %s\n", fn
) ;
403 /* fp = (FILE *) fopen64(fn, "r"); */
404 if (( fp
= fopen(fn
, "r")) == NULL
) {
406 fprintf(stderr
,"tsInitTileSet: can not open %s\n",fn
) ;
410 xdrs
= (XDR
*) malloc(sizeof(XDR
));
411 xdrstdio_create(xdrs
, fp
, XDR_DECODE
);
413 numHeaderBytes
= 5000;
415 xdr_int(xdrs
, (int *) &globalNx
);
416 xdr_int(xdrs
, (int *) &globalNy
);
417 xdr_int(xdrs
, (int *) &tileNx
);
418 xdr_int(xdrs
, (int *) &tileNy
);
419 xdr_int(xdrs
, (int *) &extraNx
);
420 xdr_int(xdrs
, (int *) &extraNy
);
421 xdr_int(xdrs
, (int *) &numTilesX
);
422 xdr_int(xdrs
, (int *) &numTilesY
);
423 xdr_double(xdrs
, (double *) &dlat
);
424 xdr_double(xdrs
, (double *) &dlon
);
425 xdr_double(xdrs
, (double *) &lat0
);
426 xdr_double(xdrs
, (double *) &lon0
);
427 xdr_int(xdrs
, (int *) &ntiles
);
429 setWrapAroundFlags();
434 int tsPrintTileSetInfo()
439 int tsInitFileInfo (char path
[])
454 tsfOcean
.dx
[0] = 0. ;
456 if (access("RSMAS_Topo_Land.TBL", F_OK
) == 0 ) {
457 /* Read in the list of topography/land use filenames. */
458 fp
= fopen("RSMAS_Topo_Land.TBL", "r");
461 fprintf(stderr
, "tsInitFileInfo : can not open RSMAS_Topo_Land.TBL\n");
467 fgets(buff
, MAXLEN
, fp
);
469 while (fscanf(fp
, "%s %s %s", type
, res
, fn
) != EOF
) {
470 sscanf(res
, "%f", &dx
);
471 if (strcmp(type
, "landuse") == 0)
473 if ( tsfLU
.num
>= MAXTOPOFILES
) {continue;}
475 for ( i
= 0 ; i
< tsfLU
.num
; i
++ ) {
476 if ( tsfLU
.dx
[i
] > dx
) {
481 for ( i
= tsfLU
.num
; i
> n
; i
-- ) {
482 tsfLU
.dx
[i
]=tsfLU
.dx
[i
-1];
483 strcpy(tsfLU
.fn
[i
], tsfLU
.fn
[i
-1]);
486 strcpy(tsfLU
.fn
[n
], fn
);
489 else if (strcmp(type
, "topography") == 0)
491 if ( tsfTopo
.num
>= MAXTOPOFILES
) {continue;}
493 for ( i
= 0 ; i
< tsfTopo
.num
; i
++ ) {
494 if ( tsfTopo
.dx
[i
] > dx
) {
499 for ( i
= tsfTopo
.num
; i
> n
; i
-- ) {
500 tsfTopo
.dx
[i
]=tsfTopo
.dx
[i
-1];
501 strcpy(tsfTopo
.fn
[i
], tsfTopo
.fn
[i
-1]);
504 strcpy(tsfTopo
.fn
[n
], fn
);
507 else if (strcmp(type
, "bathymetry") == 0)
509 if ( tsfOcean
.num
>= MAXTOPOFILES
) {continue;}
511 for ( i
= 0 ; i
< tsfOcean
.num
; i
++ ) {
512 if ( tsfOcean
.dx
[i
] > dx
) {
517 for ( i
= tsfOcean
.num
; i
> n
; i
-- ) {
518 tsfOcean
.dx
[i
]=tsfOcean
.dx
[i
-1];
519 strcpy(tsfOcean
.fn
[i
], tsfOcean
.fn
[i
-1]);
522 strcpy(tsfOcean
.fn
[n
], fn
);
531 for ( i
= 1; i
< 10 ; i
++ ) {
532 sprintf(tsfTopo
.fn
[tsfTopo
.num
], "%s/topo.%02dkm.ts", path
, i
);
533 if (access(tsfTopo
.fn
[tsfTopo
.num
], F_OK
) == 0) { tsfTopo
.dx
[tsfTopo
.num
] = i
; tsfTopo
.num
++ ; }
535 for ( i
= 10; i
<=40 ; i
+= 10 ) {
536 sprintf(tsfTopo
.fn
[tsfTopo
.num
], "%s/topo.%02dkm.ts", path
, i
);
537 if (access(tsfTopo
.fn
[tsfTopo
.num
], F_OK
) == 0) { tsfTopo
.dx
[tsfTopo
.num
] = i
; tsfTopo
.num
++ ; }
540 for ( i
= 1; i
< 10 ; i
++ ) {
541 sprintf(tsfLU
.fn
[tsfLU
.num
], "%s/glcc.usgs20.%02dkm.ts", path
, i
);
542 if (access(tsfLU
.fn
[tsfLU
.num
], F_OK
) == 0) { tsfLU
.dx
[tsfLU
.num
] = i
; tsfLU
.num
++ ; }
544 for ( i
= 10; i
<=40 ; i
+= 10 ) {
545 sprintf(tsfLU
.fn
[tsfLU
.num
], "%s/glcc.usgs20.%02dkm.ts", path
, i
);
546 if (access(tsfLU
.fn
[tsfLU
.num
], F_OK
) == 0) { tsfLU
.dx
[tsfLU
.num
] = i
; tsfLU
.num
++ ; }
549 for ( i
= 1; i
< 10 ; i
++ ) {
550 sprintf(tsfOcean
.fn
[tsfOcean
.num
], "%s/tbase.%02dkm.ts", path
, i
);
551 if (access(tsfOcean
.fn
[tsfOcean
.num
], F_OK
) == 0) { tsfOcean
.dx
[tsfLU
.num
] = i
; tsfOcean
.num
++ ; }
553 for ( i
= 10; i
<=40 ; i
+= 10 ) {
554 sprintf(tsfOcean
.fn
[tsfOcean
.num
], "%s/tbase.%02dkm.ts", path
, i
);
555 if (access(tsfOcean
.fn
[tsfOcean
.num
], F_OK
) == 0) { tsfOcean
.dx
[tsfOcean
.num
] = i
; tsfOcean
.num
++ ; }
559 for ( i
= 0 ; i
< tsfTopo
.num
; i
++ ) {
560 fprintf(stderr
,"%02d. %s\n",i
, tsfTopo
.fn
[i
]) ;
562 for ( i
=0 ; i
< tsfLU
.num
; i
++ ) {
563 fprintf(stderr
,"%02d. %s\n",i
, tsfLU
.fn
[i
]) ;
565 for ( i
=0 ; i
< tsfOcean
.num
; i
++ ) {
566 fprintf(stderr
,"%02d. %s\n",i
, tsfOcean
.fn
[i
]) ;
574 int GET_LANDUSE ( float *adx
,
582 int *ipath
, int * ipathlen
) /* integer coded ASCII string from Funtran and len */
590 static float last_adx
= 0.0 ;
592 if ( tsFileInfo_initialized
== 0 ) {
593 for (i
= 0 ; i
< *ipathlen
; i
++ ) {
596 path
[*ipathlen
] = '\0' ;
597 tsFileInfo_initialized
= tsInitFileInfo(path
);
598 if ( tsFileInfo_initialized
== -1 ) { return(1); }
601 /* if ( fabs(last_adx - *adx) > 1.0E-6 ) { */
602 /* last_adx = *adx; */
603 if ( tsfLU
.num
> 0 ) {
604 strcpy(tsfLU_fn
, tsfLU
.fn
[tsfLU
.num
-1]);
605 for ( i
= 0; i
< tsfLU
.num
; i
++) {
607 fprintf(stderr
,"%d fn %s dx %f adx %f\n",i
,tsfLU
.fn
[i
],tsfLU
.dx
[i
],*adx
) ;
609 if (tsfLU
.dx
[i
] > *adx
) {
610 strcpy(tsfLU_fn
, tsfLU
.fn
[i
-1]);
616 fprintf(stderr
, "Not found LANDUSE datasets!\n");
622 /* Get the land use. */
623 if (tsInitTileSet(tsfLU_fn
)) { return(1); }
625 for ( j
= 0; j
< *jxxn
; j
++) {
627 for ( i
= 0; i
< *iyyn
; i
++) {
628 lat
= xlat
[offset
+ i
];
629 lon
= xlon
[offset
+ i
];
631 tsLatLonToGridpoint(lat
,lon
,&fix
,&fiy
);
634 tv
= tsGetValueInt(ix
, iy
);
636 /* Set out-of-range values to water. */
637 if (tv
< 0.9 || tv
> 24.1) tv
= 16.0;
639 landuse
[offset
+ i
] = tv
;
645 int GET_TERRAIN ( float *adx
,
653 int *ipath
, int * ipathlen
) /* integer coded ASCII string from Funtran and len */
661 static float last_adx
= 0.0 ;
663 if ( tsFileInfo_initialized
== 0 ) {
664 for (i
= 0 ; i
< *ipathlen
; i
++ ) {
667 path
[*ipathlen
] = '\0' ;
668 tsFileInfo_initialized
= tsInitFileInfo(path
);
669 if ( tsFileInfo_initialized
== -1 ) { return(1); }
672 /* Use the data with the largest spacing less than the grid
673 spacing specified in the argument list. */
674 /* if ( fabs(last_adx - *adx) > 1.0E-6 ) { */
675 /* last_adx = *adx; */
676 if ( tsfTopo
.num
> 0 ) {
677 strcpy(tsfTopo_fn
, tsfTopo
.fn
[tsfTopo
.num
-1]);
678 for (i
= 0; i
< tsfTopo
.num
; i
++) {
680 fprintf(stderr
,"%d fn %s dx %f adx %f\n",i
,tsfTopo
.fn
[i
],tsfTopo
.dx
[i
],*adx
) ;
682 if ( tsfTopo
.dx
[i
] > *adx
) {
683 strcpy(tsfTopo_fn
, tsfTopo
.fn
[i
-1]);
689 fprintf(stderr
,"Not found GTOPO datasets\n");
695 if ( tsfOcean
.num
> 0 ) {
696 strcpy(tsfOcean_fn
, tsfOcean
.fn
[tsfOcean
.num
-1]);
697 for ( i
= 0; i
< tsfOcean
.num
; i
++) {
698 if (tsfOcean
.dx
[i
] > *adx
) {
699 strcpy(tsfOcean_fn
, tsfOcean
.fn
[i
-1]);
705 fprintf(stderr
, "Not found TBASE datasets!\n");
712 /* First get the terrain from GTOPO30. */
713 if (tsInitTileSet(tsfTopo_fn
)) { return(1); }
715 for ( j
= 0; j
< *jxxn
; j
++)
717 for ( i
= 0; i
< *iyyn
; i
++)
719 lat
= xlat
[offset
+ i
];
720 lon
= xlon
[offset
+ i
];
722 tsLatLonToGridpoint(lat
,lon
,&fix
,&fiy
);
723 tv
= tsGetValue(fix
, fiy
);
724 terrain
[offset
+ i
] = tv
;
730 /* Next get the terrain from TBASE. */
731 if (tsInitTileSet(tsfOcean_fn
)) { return(1); }
733 for ( j
= 0; j
< *jxxn
; j
++)
735 for ( i
= 0; i
< *iyyn
; i
++)
737 lat
= xlat
[offset
+ i
];
738 lon
= xlon
[offset
+ i
];
740 tsLatLonToGridpoint(lat
,lon
,&fix
,&fiy
);
741 tv
= tsGetValue(fix
, fiy
);
742 if (isMissing(terrain
[offset
+i
]))
744 if (tv
< 0.0) tv
= 0.0;
745 terrain
[offset
+ i
] = tv
;
755 int get_bathymetry_(float *tadx
,
765 int *ipath
, int * ipathlen
) /* integer coded ASCII string from Funtran and len */
771 double fix
, fiy
, lat
, lon
;
778 /* Set grid resolution to .1 km to get highest resolution data possible. */
781 if ( tsFileInfo_initialized
== 0 ) {
782 for (i
= 0 ; i
< *ipathlen
; i
++ ) {
785 path
[*ipathlen
] = '\0' ;
786 tsFileInfo_initialized
= tsInitFileInfo(path
);
787 if ( tsFileInfo_initialized
== -1 ) { return(1); }
790 /* Get the water depth from TBASE. */
791 if ( tsfOcean
.num
> 0 ) {
792 /* Use the data with highest resolution possible. */
794 strcpy(fn
, tsfOcean
.fn
[tsfOcean
.num
-1]);
795 for ( i
= 0; i
< tsfOcean
.num
; i
++)
797 if (tsfOcean
.dx
[i
] < maxdx
) continue;
798 if ( tsfOcean
.dx
[i
] < adx
)
800 maxdx
= tsfOcean
.dx
[i
];
801 strcpy(fn
, tsfOcean
.fn
[i
]);
805 if (tsInitTileSet(fn
))
810 for ( i
= 0; i
< nx
*ny
; i
++)
815 for ( j
= 0; j
< *jxxn
; j
++)
817 for ( i
= 0; i
< *iyyn
; i
++)
819 lat
= xlat
[offset
+ i
];
820 lon
= xlon
[offset
+ i
];
822 tsLatLonToGridpoint(lat
,lon
,&fix
,&fiy
);
823 tv
= tsGetValue(fix
, fiy
);
824 if (isMissing(depth
[offset
+i
]))
826 depth
[offset
+ i
] = -tv
;
833 fprintf(stderr
, "Not found TBASE datasets!\n");
838 /* Next get the land use. */
839 if ( tsfLU
.num
> 0 ) {
840 /* Use the data with the largest spacing less than the grid
841 spacing specified in the argument list. */
843 strcpy(fn
, tsfLU
.fn
[tsfLU
.num
-1]);
844 for ( i
= 0; i
< tsfLU
.num
; i
++)
846 if (tsfLU
.dx
[i
] < maxdx
) continue;
847 if (tsfLU
.dx
[i
] < adx
)
850 strcpy(fn
, tsfLU
.fn
[i
]);
854 if (tsInitTileSet(fn
))
859 for ( j
= 0; j
< *jxxn
; j
++)
861 for ( i
= 0; i
< *iyyn
; i
++)
863 lat
= xlat
[offset
+ i
];
864 lon
= xlon
[offset
+ i
];
866 tsLatLonToGridpoint(lat
,lon
,&fix
,&fiy
);
869 tv
= tsGetValueInt(ix
, iy
);
871 /* Set out-of-range values to water. */
872 if (tv
< 0.9 || tv
> 24.1) tv
= 16.0;
874 if (fabs(tv
- 16.0) < 0.1)
879 if (depth
[offset
+ i
] < *mindepth
) depth
[offset
+ i
] = *mindepth
;
883 if (depth
[offset
+ i
] < -(*zlimww3
) )
885 /* Water depth below zlimww3, so turn this point
887 depth
[offset
+ i
] = -0.1;
889 else if (depth
[offset
+ i
] < *mindepth
)
891 depth
[offset
+ i
] = *mindepth
;
897 /* Land. Set depth to 0.0. */
898 depth
[offset
+ i
] = 0.0;
905 fprintf(stderr
, "Not found LANDUSE datasets!\n");