root/cdat/trunk/libcdms/src/cdunif/gaddes.c

Revision 2342, 61.4 kB (checked in by drach, 6 years ago)

Removed spurious calendar error.

Line 
1 /* Copyright (c) 1987-1995 by Brian Doty.  All Rights Reserved.
2
3    See file COPYRIGHT for liability information.
4
5    Permission is granted for usage of source code on an individual
6    basis only.  You are in violation of copyright law if you have
7    possession of this source code without specific permission from
8    Brian Doty.  This source code may not be redistributed in any way,
9    in whole or in part.  You may use this source code to:
10         - understand GrADs functionality
11         - make minor enhancements to the GrADS program
12         - correct bugs in the GrADs program
13    All other uses ARE PROHIBITED, without specific written permission
14    for such use.  You agree that if you make any modifications to the
15    source code, you will provide such modifications to Brian Doty for
16    possible inclusion into the distributed version of GrADS (attribution
17    will be made if requested).  */
18
19
20 #include <stdio.h>
21 #include <math.h>
22 #include <ctype.h>
23 #ifndef __APPLE__
24 #include <malloc.h>
25 #endif
26 #include "grads.h"
27
28 /*mf 961205 --- expose Mike Fiorino's global struct to these routines for 365 day calandars mf*/
29 extern struct gamfcmn mfcmn;
30 /*mf 961205 --- expose Mike Fiorino's global struct to these routines for 365 day calandars mf*/
31
32 static char pout[512];
33 FILE *descr;      /* File descriptor pointer */
34 static FILE *pdfi;       /* File descriptor for pdef file */
35
36 void ll2eg (int , int, float *, float, float, float *, float *, float *) ;
37 void ll2pse(int, int, float *, float, float, float *, float *);
38 void ll2ops (float *, float , float , float *, float *) ;
39
40
41 /* Read a GrADS data descriptor file and fill in the information
42    into a gafile structure.  The gafile structure should be
43    allocated and must be initialized by getpfi.  If this routine
44    returns an error, release the pfi structure and allocated
45    storage via frepfi.  mflag indicates whether to read the
46    stnmap/index file; if this routine is being called to
47    preprocess the dd file then this flag should be 0. */
48
49 int gaddes (char *name, struct gafile *pfi, int mflag) {
50   struct gavar *pvar;
51   struct dt tdef,tdefi,dt1,dt2;
52   struct gaindx *pindx;
53   float *vals;
54   int size,rc,len,swpflg,cnt;
55   char rec[512], mrec[512], *ch, *dn, *pos, *sname ; /*mf mf*/
56   int flgs[8],cflg,i,j,err,hdrb,trlb,mflflg,crayflg=0;
57   int mcnt,maxlv,maxct;
58   int levs,acum,acumvz,fpos,recacm;
59   float temp,v1,v2;
60   FILE *mfile;
61   char pdefnm[256];
62   int pdefop1, pdefop2;
63
64   /*mf .... mf*/
65   int nzstride=0,first=1;
66   int levsua=0,acumstride=0;
67   unsigned char vermap;
68   int idum;
69   float fdum;
70   unsigned char urec[4];
71   int diag=0;
72   /*mf .... mf*/
73
74   static char *errs[9] = {"XDEF","YDEF","ZDEF","TDEF","UNDEF",
75                             "DSET","VARS","TITLE","DTYPE"};
76
77  /*mf --- define here vice grads.c for cdunif.c mf*/
78   mfcmn.fullyear=-999;
79
80   /*
81 #if GRADS_CDUNIF == 1
82    mfcmn.fullyear=-999;
83 #endif
84 */
85   hdrb = 0;
86   trlb = 0;
87   pdfi = NULL;
88   mflflg = 0;                   /* map file not open */
89   pfi->mfile = NULL;
90
91   mcnt = -1;
92
93   descr = fopen (name, "r");
94
95   /* default suffix of .ctl */
96
97   sname=NULL;
98   if (descr == NULL) {
99     sname = (char *)malloc(strlen(name)+5);
100     if(sname == NULL) {
101       gaprnt(0,"malloc error in creating date descriptor file name\n");
102       return(1);
103     }
104     for(i=0;i<=strlen(name);i++) *(sname+i)=*(name+i);
105     strcat(sname,".ctl");
106     descr = fopen (sname, "r");
107   }
108
109   if (descr==NULL) {
110     gaprnt (0,"Open Error:  Can't open description file\n");
111     return(1);
112   }
113
114   if(sname !=NULL) {
115     getwrd (pfi->dnam,sname,256);
116     free(sname);
117   } else {
118     getwrd (pfi->dnam,name,256);
119   }
120
121   /* initialize error flags */
122
123   for (i=0;i<8;i++) flgs[i] = 1;
124
125   /*mf initialize the calendar to standard and cray_ieee to 0 mf*/
126
127   pfi->calendar=0;
128   pfi->cray_ieee=0;
129
130 /*mf---------mf*/
131
132   /* parse the dd  file */
133
134   while (fgets(rec,512,descr)!=NULL) {
135     strcpy (mrec,rec);
136     lowcas(rec);
137
138     if ( (cmpwrd("*",rec)) || !isalnum(rec[0]) ) {
139       cflg = 1;
140
141     } else if (cmpwrd("byteswapped",rec)) {
142       pfi->bswap = 1;
143
144
145     } else if (cmpwrd("fileheader",rec)) {
146       if ( (ch=nxtwrd(rec))==NULL ) {
147         gaprnt (1,"Description file warning: Missing fileheader length\n");
148       } else {
149         ch = intprs(ch,&(pfi->fhdr));
150         if (ch==NULL) {
151           gaprnt (1,"Fileheader record invalid\n");
152           pfi->fhdr = 0;
153         }
154       }
155
156
157     } else if (cmpwrd("xyheader",rec)) {
158
159
160       if ( (ch=nxtwrd(rec))==NULL ) {
161         gaprnt (1,"Description file warning: Missing xy grid header length\n");
162       } else {
163         ch = intprs(ch,&(pfi->xyhdr));
164         if (ch==NULL) {
165           gaprnt (1,"xy grid header length invalid\n");
166           pfi->xyhdr = 0;
167         } else {
168           pfi->xyhdr = pfi->xyhdr / sizeof(float);
169         }
170       }
171
172
173     } else if (cmpwrd("theader",rec)) {
174       if ( (ch=nxtwrd(rec))==NULL ) {
175         gaprnt (1,"Description file warning: Missing time chunk header length\n");
176       } else {
177         ch = intprs(ch,&(pfi->thdr));
178         if (ch==NULL) {
179           gaprnt (1,"time chunk grid header length invalid\n");
180           pfi->thdr = 0;
181         } else {
182           pfi->thdr = pfi->thdr / sizeof(float);
183         }
184       }
185
186
187     } else if (cmpwrd("format",rec) || cmpwrd("options",rec)) {
188       if ( (ch=nxtwrd(rec))==NULL ) {
189         gaprnt (1,"Description file warning: Missing options keyword\n");
190       } else {
191         while (ch!=NULL) {
192           if (cmpwrd("sequential",ch)) pfi->seqflg = 1;
193           else if (cmpwrd("yrev",ch)) pfi->yrflg = 1;
194           else if (cmpwrd("zrev",ch)) pfi->zrflg = 1;
195           else if (cmpwrd("template",ch)) pfi->tmplat = 1;
196           else if (cmpwrd("byteswapped",ch)) pfi->bswap = 1;
197           else if (cmpwrd("cray_32bit_ieee",ch) && GRADS_CRAY) pfi->cray_ieee = 1;
198           else if (cmpwrd("cray_32bit_ieee",ch) && !GRADS_CRAY) pfi->cray_ieee = 0;
199           else if (cmpwrd("365_day_calendar",ch)) pfi->calendar=1;
200           else if (cmpwrd("big_endian",ch)) {
201             if (!BYTEORDER) pfi->bswap = 1;
202           }
203           else if (cmpwrd("little_endian",ch)) {
204             if (BYTEORDER) pfi->bswap = 1;
205           }
206           else {
207             gaprnt (0,"Open Error:  Data file type invalid\n");
208             goto err9;
209           }
210           ch = nxtwrd(ch);
211         }
212       }
213
214     } else if (cmpwrd("trailerbytes",rec)) {
215       if ( (ch=nxtwrd(rec))==NULL ) {
216         gaprnt (1,"Trailerbytes record invalid\n");
217       } else {
218         ch = intprs(ch,&trlb);
219         if (ch==NULL) {
220           gaprnt (1,"Trailerbytes record invalid\n");
221           trlb = 0;
222         } else {
223           trlb = trlb/4;
224         }
225       }
226
227     } else if (cmpwrd("headerbytes",rec)) {
228       if ( (ch=nxtwrd(rec))==NULL ) {
229         gaprnt (1,"Headerbytes record invalid\n");
230       } else {
231         ch = intprs(ch,&hdrb);
232         if (ch==NULL) {
233           gaprnt (1,"Headerbytes record invalid\n");
234           hdrb = 0;
235         } else {
236           hdrb = hdrb/4;
237         }
238       }
239
240     } else if (cmpwrd("dtype",rec)) {
241       if ( (ch=nxtwrd(rec))==NULL ) {
242         gaprnt (1,"Description file warning: Missing data type\n");
243         gaprnt (1,"   Assuming data file type is grid\n");
244       }
245       if (cmpwrd("station",ch)) {
246         pfi->type = 2;
247         flgs[0] = 0;
248         flgs[1] = 0;
249         flgs[2] = 0;
250
251       } else if (cmpwrd("grib",ch)) {
252         pfi->idxflg = 1;
253         if ( (ch=nxtwrd(ch))!=NULL ) {
254           if ( intprs(ch,&(pfi->grbgrd))==NULL) {
255             gaprnt (1,"Description file warning: Invalid GRIB option\n");
256             pfi->grbgrd = -999;
257           }
258         }
259       } else {
260         gaprnt (0,"Open Error:  Data file type invalid\n");
261         goto err9;
262       }
263
264     } else if (cmpwrd("title",rec)) {
265       if ( (ch=nxtwrd(mrec))==NULL ) {
266         gaprnt (1,"Description file warning: Missing title string\n");
267       } else {
268         getstr (pfi->title,ch,79);
269         flgs[7] = 0;
270       }
271
272     } else if (cmpwrd("dset",rec)) {
273       ch = nxtwrd(mrec);
274       if (ch==NULL) {
275         gaprnt (0,"Open Error:  Data file name is missing\n");
276         goto err9;
277       }
278       if (*ch=='^' || *ch=='$') {
279         fnmexp (pfi->name,ch,name);
280       } else {
281         getwrd (pfi->name,ch,256);
282       }
283       flgs[5] = 0;
284
285     } else if (cmpwrd("stnmap",rec) || cmpwrd("index",rec)) {
286
287 /*mf -----
288
289   map file processing -- gribmap
290
291 -----mf*/
292
293       if (cmpwrd("index",rec)) pfi->idxflg = 1;
294       ch = nxtwrd(mrec);
295       if (ch==NULL) {
296         gaprnt (0,"Open Error:  Station or Index Map file name is missing\n");
297         goto err9;
298       }
299       if (*ch=='^' || *ch=='$') {
300         fnmexp (pout, ch, name);
301       } else {
302         getwrd (pout,ch,100);
303       }
304       len = 0;
305       while (*(pout+len)) len++;
306       pfi->mnam = (char *)malloc(len+3);
307       if (pfi->mnam==NULL) goto err8;
308       strcpy (pfi->mnam,pout);
309       if (mflag) {
310         mfile = NULL;
311         mfile = fopen (pout, "rb");
312         if (mfile==NULL) {
313           gaprnt (0,"Open Error:  Can't open Station/Index map file ");
314           gaprnt (0,pout);
315           gaprnt (0,"\n");
316           goto err9;
317         }
318
319
320         mflflg = 1;
321         swpflg = 0;
322
323 /*---
324   GRIB data - load the map
325 ---*/
326
327         if (pfi->idxflg) {
328           pindx = (struct gaindx *)malloc(sizeof(struct gaindx));
329           if (pindx==NULL) goto err8;
330           pfi->pindx = pindx;
331
332 /*
333    check the version number
334 */
335
336           fseek(mfile,1,0);
337           fread(&vermap,sizeof(unsigned char),1,mfile);
338           if(diag) printf("ddd gribmap vermap =%d\n",vermap);
339
340           if(vermap == 2) {
341
342             fseek(mfile,2,0);
343             fread(mrec,sizeof(unsigned char),4,mfile);
344             pindx->hinum=gagby(mrec,0,4);
345             if(diag) printf("ddd  hinum = %d\n",pindx->hinum);
346
347             fread(mrec,sizeof(unsigned char),4,mfile);
348             pindx->hfnum=gagby(mrec,0,4);
349             if(diag) printf("ddd hfnum = %d\n",pindx->hfnum);
350
351             fread(mrec,sizeof(unsigned char),4,mfile);
352             pindx->intnum=gagby(mrec,0,4);
353             if(diag) printf("ddd intnum = %d\n",pindx->intnum);
354
355             fread(mrec,sizeof(unsigned char),4,mfile);
356             pindx->fltnum=gagby(mrec,0,4);
357             if(diag) printf("ddd fltnum = %d\n",pindx->fltnum);
358
359 /* skip the begining time struct info */
360
361             fread(mrec,sizeof(unsigned char),7,mfile);
362
363             pindx->hipnt = NULL;
364             pindx->hfpnt = NULL;
365             pindx->intpnt = NULL;
366             pindx->fltpnt = NULL;
367
368             if (pindx->hinum>0) {
369               pindx->hipnt = (int *)malloc(sizeof(int)*pindx->hinum);
370               if (pindx->hipnt==NULL) goto err8;
371
372               for(i=0;i<pindx->hinum;i++) {
373                 fread(mrec,sizeof(unsigned char),4,mfile);
374                 idum=gagby(mrec,0,4);
375                 if(gagbb(mrec,0,1)) idum=-idum;
376                 *(pindx->hipnt+i)=idum;
377                 if(diag) printf("ddd 1 i = %d pindx->hipnt = %d\n",i,idum);
378               }
379
380             }
381
382
383             if (pindx->hfnum>0) {
384               pindx->hfpnt = (float *)malloc(sizeof(float)*pindx->hfnum);
385               if (pindx->hfpnt==NULL) goto err8;
386               fread (pindx->hfpnt,sizeof(float),pindx->hfnum,mfile);
387             }
388
389             if (pindx->intnum>0) {
390               pindx->intpnt = (int *)malloc(sizeof(int)*pindx->intnum);
391               if (pindx->intpnt==NULL) goto err8;
392               for(i=0;i<pindx->intnum;i++) {
393                 fread(mrec,sizeof(unsigned char),4,mfile);
394                 idum=gagby(mrec,0,4);
395                 if(gagbb(mrec,0,1)) idum=-gagbb(mrec,1,31);
396                 *(pindx->intpnt+i)=idum;
397                 if(diag) printf("ddd 2 i = %d pindx->intpnt = %d\n",i,idum);
398               }
399
400             }
401
402             if (pindx->fltnum>0) {
403               pindx->fltpnt = (float *)malloc(sizeof(float)*pindx->fltnum);
404               if (pindx->fltpnt==NULL) goto err8;
405
406               for(i=0;i<pindx->fltnum;i++) {
407                 fread(urec,sizeof(unsigned char),4,mfile);
408                 fdum=ibm2flt(urec);
409                 *(pindx->fltpnt+i)=fdum;
410                 if(diag) printf("ddd 3 i = %d pindx->fltpnt = %g\n",i,fdum);
411               }
412
413             }
414
415           } else {
416
417             fseek (mfile,0L,0);
418             fread (pindx,sizeof(struct gaindx),1,mfile);
419             if (pindx->type>>24 > 0) swpflg=1;
420             if (swpflg) gabswp((float *)pindx,5);
421             pindx->hipnt = NULL;
422             pindx->hfpnt = NULL;
423             pindx->intpnt = NULL;
424             pindx->fltpnt = NULL;
425             if (pindx->hinum>0) {
426               pindx->hipnt = (int *)malloc(sizeof(int)*pindx->hinum);
427               if (pindx->hipnt==NULL) goto err8;
428               fread (pindx->hipnt,sizeof(int),pindx->hinum,mfile);
429               if (swpflg) gabswp((float *)(pindx->hipnt),pindx->hinum);
430             }
431             if (pindx->hfnum>0) {
432               pindx->hfpnt = (float *)malloc(sizeof(float)*pindx->hfnum);
433               if (pindx->hfpnt==NULL) goto err8;
434               fread (pindx->hfpnt,sizeof(float),pindx->hfnum,mfile);
435               if (swpflg) gabswp(pindx->hfpnt,pindx->hfnum);
436             }
437             if (pindx->intnum>0) {
438               pindx->intpnt = (int *)malloc(sizeof(int)*pindx->intnum);
439               if (pindx->intpnt==NULL) goto err8;
440               fread (pindx->intpnt,sizeof(int),pindx->intnum,mfile);
441               if (swpflg) gabswp((float *)(pindx->intpnt),pindx->intnum);
442             }
443             if (pindx->fltnum>0) {
444               pindx->fltpnt = (float *)malloc(sizeof(float)*pindx->fltnum);
445               if (pindx->fltpnt==NULL) goto err8;
446               fread (pindx->fltpnt,sizeof(float),pindx->fltnum,mfile);
447               if (swpflg) gabswp(pindx->fltpnt,pindx->fltnum);
448             }
449
450           }
451
452 /*mf -----
453
454   map file processing -- stnmap
455
456 -----mf*/
457
458         } else {
459
460 /*mf version detection mf*/
461
462           fread(rec,1,16,mfile);  /* minimum map file is 16 bytes */
463
464           vermap=1;
465           if(strncmp(rec,"GrADS_stnmapV002",16) == 0) {
466             vermap=2;
467           }
468
469           if(vermap == 2) {
470
471             fread(mrec,sizeof(unsigned char),4,mfile);
472             idum=gagby(mrec,0,4);
473             if(gagbb(mrec,0,1)) idum=-idum;
474             mcnt=idum;
475
476             fread(mrec,sizeof(unsigned char),4,mfile);
477             idum=gagby(mrec,0,4);
478             if(gagbb(mrec,0,1)) idum=-idum;
479             maxlv=idum;
480
481             pfi->tstrt = (int *)malloc(sizeof(int)*mcnt);
482             pfi->tcnt = (int *)malloc(sizeof(int)*mcnt);
483
484             for(i=0;i<mcnt;i++) {
485               fread(mrec,sizeof(unsigned char),4,mfile);
486               idum=gagby(mrec,0,4);
487               if(gagbb(mrec,0,1)) idum=-idum;
488               *(pfi->tstrt+i)=idum;
489             }
490
491             for(i=0;i<mcnt;i++) {
492               fread(mrec,sizeof(unsigned char),4,mfile);
493               idum=gagby(mrec,0,4);
494               if(gagbb(mrec,0,1)) idum=-idum;
495               *(pfi->tcnt+i)=idum;
496             }
497
498        
499           } else if(vermap ==1) {
500
501 /* reposition and read two local ints for version 1 map*/
502
503             fseek (mfile,0L,0);
504
505             fread (&mcnt,sizeof(int),1,mfile);
506             fread (&maxlv,sizeof(int),1,mfile);
507
508             if (maxlv>>24 > 0) swpflg = 1;
509             if (swpflg) {
510               gabswp((float *)(&mcnt),1);
511               gabswp((float *)(&maxlv),1);
512             }
513             pfi->tstrt = (int *)malloc(sizeof(int)*mcnt);
514             pfi->tcnt = (int *)malloc(sizeof(int)*mcnt);
515             fread (pfi->tstrt,sizeof(int),mcnt,mfile);
516             fread (pfi->tcnt,sizeof(int),mcnt,mfile);
517             if (swpflg) {
518               gabswp((float *)pfi->tstrt,1);
519               gabswp((float *)pfi->tcnt,1);
520             }
521             pfi->mtype = 1;
522
523           }
524
525         }
526
527         if(mfile != NULL) fclose (mfile);
528         mflflg = 0;
529
530       } /* END OF mpfile check */
531
532
533     } else if (cmpwrd("toff",rec)) {
534       ch = nxtwrd(rec);
535       if (ch==NULL) {
536         gaprnt (0,"Open Error:  Missing toff value\n");
537         goto err9;
538       }
539       pos = intprs(ch,&(pfi->tlpst));
540       if (pos==NULL || pfi->tlpst>=pfi->dnum[3]) {
541         gaprnt (0,"Open Error:  Invalid toff value\n");
542         goto err9;
543       }
544       pfi->tlpflg = 1;
545
546
547     }  else if (cmpwrd("undef",rec)) {
548       ch = nxtwrd(rec);
549       if (ch==NULL) {
550         gaprnt (0,"Open Error:  Missing undef value\n");
551         goto err9;
552       }
553       pos = valprs(ch,&(pfi->undef));
554       if (pos==NULL) {
555         gaprnt (0,"Open Error:  Invalid undef value\n");
556         goto err9;
557       }
558       if (SETMISS) {
559         pfi->ulow = fabs(pfi->undef/EPSILON);
560         pfi->uhi = pfi->undef + pfi->ulow;
561         pfi->ulow = pfi->undef - pfi->ulow;
562       }
563       flgs[4] = 0;
564
565     } else if (cmpwrd("pdef",rec)) {
566       if ( (ch = nxtwrd(rec)) == NULL) goto errm;
567       if ( (pos = intprs(ch,&(pfi->ppisiz)))==NULL) goto errm;
568       if ( (ch = nxtwrd(ch)) == NULL) goto errm;
569       if ( (pos = intprs(ch,&(pfi->ppjsiz)))==NULL) goto errm;
570       if ( (ch = nxtwrd(ch)) == NULL) goto errm;
571       if (cmpwrd("nps",ch)) {pfi->ppflag=1; pfi->ppwrot=1; cnt=4;}
572       else if (cmpwrd("sps",ch)) {pfi->ppflag=2; pfi->ppwrot=1; cnt=4;}
573       else if (cmpwrd("lcc",ch)) {pfi->ppflag=3; pfi->ppwrot=0; cnt=9;}
574       else if (cmpwrd("eta.u",ch)) {pfi->ppflag=4; pfi->ppwrot=1; cnt=4;}
575       else if (cmpwrd("pse",ch)) {pfi->ppflag=5; pfi->ppwrot=0; cnt=7;}
576       else if (cmpwrd("ops",ch)) {pfi->ppflag=6; pfi->ppwrot=0; cnt=8;}
577       else if (cmpwrd("bilin",ch)) {pfi->ppflag=7; pfi->ppwrot=1; cnt=0;}
578       else if (cmpwrd("file",ch)) {pfi->ppflag=8; pfi->ppwrot=1; cnt=1;}
579       else goto errm;
580       for (i=0; i<cnt; i++) {
581         if ( (ch = nxtwrd(ch)) == NULL) goto errm;
582         if ( (pos = valprs(ch,&(pfi->ppvals[i])))==NULL) goto errm;
583       }
584       pdefop1 = 0; pdefop2 = 0;
585       if (pfi->ppflag==8) {
586         i = (int)(pfi->ppvals[0]+0.1);
587         if (i<1 || i>8) goto errm;
588       }
589       if (pfi->ppflag==7 || pfi->ppflag==8) {
590         if ( (ch = nxtwrd(ch)) == NULL) goto errm;
591         if (cmpwrd("stream",ch)) pdefop1 = 1;
592         else if (cmpwrd("sequential",ch)) pdefop1 = 2;
593         else goto errm;
594         if ( (ch = nxtwrd(ch)) == NULL) goto errm;
595         if (cmpwrd("binary",ch)) pdefop2 = 1;
596         if (cmpwrd("binary-big",ch)) pdefop2 = 2;
597         if (cmpwrd("binary-little",ch)) pdefop2 = 3;
598         else if (cmpwrd("packed",ch)) pdefop2 = 4;
599         else goto errm;
600         if ( (ch = nxtwrd(ch)) == NULL) goto errm;
601         if (*ch=='^' || *ch=='$') {
602           fnmexp (pdefnm,ch,name);
603         } else {
604           getwrd (pdefnm,ch,256);
605         }
606         pdfi = fopen(pdefnm,"rb");
607         if (pdfi==NULL) {
608           gaprnt (0,"Error opening pdef file\n");
609           sprintf (pout, "  File name is:  %s\n",pdefnm);
610           gaprnt (0,pout);
611           goto errm;
612         }
613       }
614
615     }  else if (cmpwrd("xdef",rec)) {
616
617       if (pfi->type == 2) continue;
618       if ( (ch = nxtwrd(rec)) == NULL) goto err1;
619       if ( (pos = intprs(ch,&(pfi->dnum[0])))==NULL) goto err1;
620       if (*pos!=' ') goto err1;
621       if ( (ch = nxtwrd(ch))==NULL) goto err2;
622       if (cmpwrd("linear",ch)) {
623         rc = deflin(ch, pfi, 0, 0);
624         if (rc==-1) goto err8;
625         if (rc) goto err9;
626         v2 = *(pfi->grvals[0]);
627         v1 = *(pfi->grvals[0]+1) + v2;
628         temp = v1+((float)(pfi->dnum[0]))*v2;
629         temp=temp-360.0;
630         if (fabs(temp-v1)<0.01) pfi->wrap = 1;
631       }
632       else if (cmpwrd("levels",ch)) {
633         if (pfi->dnum[0]<1) goto err7;
634         rc = deflev (ch, rec, pfi, 0);
635         if (rc==-1) goto err8;
636         if (rc) goto err9;
637       } else goto err2;
638       flgs[0] = 0;
639
640     } else if (cmpwrd("ydef",rec)) {
641       if (pfi->type == 2) continue;
642       if ( (ch = nxtwrd(rec)) == NULL) goto err1;
643       if ( (pos = intprs(ch,&(pfi->dnum[1])))==NULL) goto err1;
644       if (*pos!=' ') goto err1;
645       if ( (ch = nxtwrd(ch))==NULL) goto err2;
646       if (cmpwrd("linear",ch)) {
647         rc = deflin(ch, pfi, 1, 0);
648         if (rc==-1) goto err8;
649         if (rc) goto err9;
650       } else if (cmpwrd("levels",ch)) {
651         if (pfi->dnum[1]<1) goto err7;
652         rc = deflev (ch, rec, pfi, 1);
653         if (rc==-1) goto err8;
654         if (rc) goto err9;
655       } else if (cmpwrd("gausr40",ch)) {
656         if ( (ch = nxtwrd(ch))==NULL) goto err3;
657         if ( (pos = intprs(ch,&i))==NULL) goto err3;
658         pfi->grvals[1] = gagaus(i,pfi->dnum[1]);
659         if (pfi->grvals[1]==NULL) goto err9;
660         pfi->abvals[1] = pfi->grvals[1];
661         pfi->ab2gr[1] = lev2gr;
662         pfi->gr2ab[1] = gr2lev;
663         pfi->linear[1] = 0;
664       } else if (cmpwrd("mom32",ch)) {
665         if ( (ch = nxtwrd(ch))==NULL) goto err3;
666         if ( (pos = intprs(ch,&i))==NULL) goto err3;
667         pfi->grvals[1] = gamo32(i,pfi->dnum[1]);
668         if (pfi->grvals[1]==NULL) goto err9;
669         pfi->abvals[1] = pfi->grvals[1];
670         pfi->ab2gr[1] = lev2gr;
671         pfi->gr2ab[1] = gr2lev;
672         pfi->linear[1] = 0;
673       } else if (cmpwrd("gausr30",ch)) {
674         if ( (ch = nxtwrd(ch))==NULL) goto err3;
675         if ( (pos = intprs(ch,&i))==NULL) goto err3;
676         pfi->grvals[1] = gags30(i,pfi->dnum[1]);
677         if (pfi->grvals[1]==NULL) goto err9;
678         pfi->abvals[1] = pfi->grvals[1];
679         pfi->ab2gr[1] = lev2gr;
680         pfi->gr2ab[1] = gr2lev;
681         pfi->linear[1] = 0;
682       } else if (cmpwrd("gausr20",ch)) {
683         if ( (ch = nxtwrd(ch))==NULL) goto err3;
684         if ( (pos = intprs(ch,&i))==NULL) goto err3;
685         pfi->grvals[1] = gags20(i,pfi->dnum[1]);
686         if (pfi->grvals[1]==NULL) goto err9;
687         pfi->abvals[1] = pfi->grvals[1];
688         pfi->ab2gr[1] = lev2gr;
689         pfi->gr2ab[1] = gr2lev;
690         pfi->linear[1] = 0;
691       } else if (cmpwrd("gausr15",ch)) {
692         if ( (ch = nxtwrd(ch))==NULL) goto err3;
693         if ( (pos = intprs(ch,&i))==NULL) goto err3;
694         pfi->grvals[1] = gags15(i,pfi->dnum[1]);
695         if (pfi->grvals[1]==NULL) goto err9;
696         pfi->abvals[1] = pfi->grvals[1];
697         pfi->ab2gr[1] = lev2gr;
698         pfi->gr2ab[1] = gr2lev;
699         pfi->linear[1] = 0;
700       } else goto err2;
701       flgs[1] = 0;
702
703     } else if (cmpwrd("zdef",rec)) {
704       if (pfi->type == 2) continue;
705       if ( (ch = nxtwrd(rec)) == NULL) goto err1;
706       if ( (pos = intprs(ch,&(pfi->dnum[2])))==NULL) goto err1;
707       if (*pos!=' ') goto err1;
708       if ( (ch = nxtwrd(ch))==NULL) goto err2;
709       if (cmpwrd("linear",ch)) {
710         rc = deflin(ch, pfi, 2, 0);
711         if (rc==-1) goto err8;
712         if (rc) goto err9;
713       }
714       else if (cmpwrd("levels",ch)) {
715         if (pfi->dnum[2]<1) goto err7;
716         rc = deflev (ch, rec, pfi, 2);
717         if (rc==-1) goto err8;
718         if (rc) goto err9;
719       } else goto err2;
720       flgs[2] = 0;
721
722     } else if (cmpwrd("tdef",rec)) {
723       if ( (ch = nxtwrd(rec)) == NULL) goto err1;
724       if ( (pos = intprs(ch,&(pfi->dnum[3])))==NULL) goto err1;
725       if (*pos!=' ') goto err1;
726       if ( (ch = nxtwrd(ch))==NULL) goto err2;
727       if (cmpwrd("linear",ch)) {
728         if ( (ch = nxtwrd(ch))==NULL) goto err3;
729         tdef.yr = -1000;
730         tdef.mo = -1000;
731         tdef.dy = -1000;
732         if ( (pos = adtprs(ch,&tdef,&dt1))==NULL) goto err3;
733         if (*pos!=' ' || dt1.yr == -1000 || dt1.mo == -1000.0 ||
734             dt1.dy == -1000) goto err3;
735         if ( (ch = nxtwrd(ch))==NULL) goto err4;
736         if ( (pos = rdtprs(ch,&dt2))==NULL) goto err4;
737         v1 = (dt2.yr * 12) + dt2.mo;
738         v2 = (dt2.dy * 1440) + (dt2.hr * 60) + dt2.mn;
739         /*mf --- check if 0 dt ---mf*/
740         if( (v1 == 0) && (v2 == 0) ) goto err4a;
741         vals = (float *)malloc(sizeof(float)*8);
742         if (vals==NULL) goto err8;
743         *(vals) = dt1.yr;
744         *(vals+1) = dt1.mo;
745         *(vals+2) = dt1.dy;
746         *(vals+3) = dt1.hr;
747         *(vals+4) = dt1.mn;
748         *(vals+5) = v1;
749         *(vals+6) = v2;
750         *(vals+7) = -999.9;
751         pfi->grvals[3] = vals;
752         pfi->abvals[3] = vals;
753         pfi->linear[3] = 1;
754       } else goto err2;
755       flgs[3] = 0;
756
757     } else if (cmpwrd("vars",rec)) {
758       if ( (ch = nxtwrd(rec)) == NULL) goto err5;
759       if ( (pos = intprs(ch,&(pfi->vnum)))==NULL) goto err5;
760       size = pfi->vnum * (sizeof(struct gavar) + 7 );
761       pvar = (struct gavar *)malloc(size);
762       pfi->pvar1 = pvar;
763       i = 0;
764       while (i<pfi->vnum) {
765         if (fgets(rec,256,descr)==NULL) {
766           gaprnt (0,"Open Error:  Unexpected EOF reading variables\n");
767           sprintf (pout, "Was expecting %i records.  Found %i.\n",
768                    pfi->vnum, i);
769           gaprnt (2,pout);
770           goto retrn;
771         }
772         strcpy (mrec,rec);
773         lowcas(rec);
774         if (cmpwrd("endvars",rec)) {
775           gaprnt (0,"Open Error:  Unexpected ENDVARS record\n");
776           sprintf (pout, "Was expecting %i records.  Found %i.\n",
777                    pfi->vnum, i);
778           gaprnt (2,pout);
779           goto err9;
780         }
781         getwrd (pvar->abbrv,rec,15);
782         if ( (ch=nxtwrd(rec))==NULL) goto err6;
783         if ( (pos=intprs(ch,&(pvar->levels)))==NULL ) goto err6;
784         if ( (ch=nxtwrd(ch))==NULL) goto err6;
785         for (j=0;j<4;j++) pvar->units[j] = -999;
786         j = 0;
787         while (1) {
788           if ( (ch=intprs(ch,&(pvar->units[j])))==NULL ) goto err6;
789           while (*ch==' ') ch++;
790           if (*ch=='\0' || *ch=='\n') goto err6;
791           if (*ch!=',') break;
792           ch++;
793           while (*ch==' ') ch++;
794           if (*ch=='\0' || *ch=='\n') goto err6;
795           j++;
796           if (j>3) goto err6;
797         }
798         getstr (pvar->varnm,mrec+(ch-rec),127);
799
800 /*mf...........mf*/
801 /* initialize the var_z counter for NASA GLA format */
802         pvar->var_z = 1;
803         if(pvar->units[0] == -1 && pvar->units[1] == 10 ) {
804           nzstride++;
805         }
806
807 /* var_t is for DRS var-t transforms */
808
809         pvar->var_t = 0;
810         if(pvar->units[0] == -1 && pvar->units[1] == 20 ) pvar->var_t = 1;
811
812 /* x-y transpose for lat/lon vice lon/lat data VERY INEFFICIENT!!! */
813
814         pvar->y_x = 0;
815         if(pvar->units[0] == -1 && pvar->units[1] == 30) pvar->y_x = 1;
816
817 /*mf 961126 -  integer data types mf*/
818
819         pvar->dfrm = 0;
820         if( (pvar->units[0] == -1 && pvar->units[1] == 40 ) &&
821             (pvar->units[2] >=1 && pvar->units[2] <= 4 ) ) {
822           pvar->dfrm= pvar->units[2];
823           if ( pvar->units[2] == 2 ) pvar->dfrm=2;
824           if ( pvar->units[2] == 2 && pvar->units[3] == -1) pvar->dfrm=-2;
825
826         }
827 /* 32-bit big endian ieee to cray float */
828
829 #if GRADS_CRAY == 1
830         if( (pvar->units[0]==-1 && pvar->units[1]==50) || crayflg ) pvar->dfrm=8;
831 #endif
832
833 /*mf...........mf*/
834
835         i++; pvar++;
836       }
837       if (fgets(rec,256,descr)==NULL) {
838         gaprnt (0,"Open Error:  Missing ENDVARS statement.\n");
839         goto retrn;
840       }
841
842       lowcas(rec);
843       if (!cmpwrd("endvars",rec)) {
844         gaprnt (0,"Open Error:  Looking for ENDVARS statement\n");
845         gaprnt (0,"             Instead, found:  \n");
846         goto err9;
847       }
848       flgs[6] = 0;
849       /*
850          parse error of .ctl file
851          */
852     } else {
853       gaprnt (0,"Open Error:  Unknown keyword in description file\n");
854       goto err9;
855     }
856
857
858   }
859
860   err=0;
861   for (i=0; i<7; i++) {
862     if (flgs[i]) {
863       sprintf (pout,"Open Error:  missing %s record \n",errs[i]);
864       gaprnt (0,pout);
865       err=1;
866     }
867   }
868
869   if (err) goto retrn;
870
871   if (pfi->type>1 && mflag) {
872     if (mcnt==-1) {
873       gaprnt (0,"Open Error: missing STNMAP record\n");
874       err=1;
875     } else if (mcnt != pfi->dnum[3]) {
876       gaprnt (0,"Open Error: Inconsistent time count\n");
877       sprintf (pout,"  Count in station map file = %li\n",mcnt);
878       gaprnt (0,pout);
879       sprintf (pout,"  Count in descriptor file = %i\n",pfi->dnum[3]);
880       gaprnt (0,pout);
881       err=1;
882     }
883   }
884
885   if (err) goto retrn;
886
887   /* Figure out locations of variables within a time group */
888
889   pvar = pfi->pvar1;
890
891 /*mf------------------mf*/
892 /*
893
894    Grid data
895 */
896   if (pfi->type==1) {
897     pfi->gsiz = pfi->dnum[0] * pfi->dnum[1];
898     if (pfi->ppflag) pfi->gsiz = pfi->ppisiz * pfi->ppjsiz;
899
900 /*mf
901   add a constant xy header
902 mf*/
903     if (pfi->xyhdr) {
904       pfi->gsiz = pfi->gsiz + pfi->xyhdr;
905       }
906
907     if (pfi->seqflg) {
908       pfi->gsiz+=2;
909       if (hdrb>0) hdrb+=2;
910       pvar->offset = 1+hdrb;
911       acum = 1+hdrb;
912     } else {
913       pvar->offset = hdrb;
914       acum = hdrb;
915     }
916     levs = pvar->levels;
917     if (levs==0) levs=1;
918     pvar->recoff = 0;
919     recacm = 0;
920     pvar++;
921
922     acumvz=acum;
923
924     for (i=1; i<pfi->vnum; i++) {
925
926 /* NASA GLA FORMAT CHECKS */
927 /* upper air fields which var and z are transposed*/
928
929       if( (pvar->units[0]==-1) &&
930          (pvar->units[1]==10) &&
931          (pvar->units[2]==1) ) {
932                                                
933         levsua = pvar->levels;
934         acum = acum + pfi->gsiz;
935         pvar->var_z = nzstride;
936
937 /* diagnstotic fields AFTER  upper air fields which are in GrADS normal order */
938
939       } else if( (pvar->units[0]==-1) &&
940                 (pvar->units[1]==10) &&
941                 (pvar->units[2]==2) ) {
942         if(first) {
943           acumstride = acumstride + nzstride*levsua*pfi->gsiz;
944           acum = acumstride + (pvar->levels*pfi->gsiz) ;
945           first = 0 ;
946         } else {
947           acum = acum + (levs*pfi->gsiz);
948         }
949
950       } else if(pvar->var_t) {   /* DRS transposition of var and t */
951
952         if(pfi->tmplat) {   /* time template, read the third unit param
953                                for the size of each chunk in a file */
954
955           if(pvar->units[2] != -999) {
956             acum = acum + levs*(pfi->gsiz)*(pvar->units[1]);
957           } else {
958             gaprnt (0,"Using time templat and 4-D variables, # times / file not specified\n");
959             gaprnt (0,"Defaulting to the number of times in the .ctl file\n");
960             acum = acum + levs*(pfi->gsiz)*(pfi->dnum[3]);
961           }
962         } else {
963           acum = acum + levs*(pfi->gsiz)*(pfi->dnum[3]);
964         }
965
966       } else  {                                 /* simple GrADS */
967
968         acum = acum + (levs*pfi->gsiz);
969         acumstride = acum ;
970
971       }
972
973       recacm += levs;
974       pvar->offset = acum;
975       pvar->recoff = recacm;
976       levs = pvar->levels;
977       if (levs==0) levs=1;
978       pvar++;
979
980     }
981
982     recacm += levs;
983
984 /*mf 960514 correct for case where the last variable is a NASA UA */
985
986     pvar--;
987     if( (pvar->units[0]==-1) &&
988        (pvar->units[1]==10) &&
989        (pvar->units[2]==1) ) {
990       acum = acumvz + recacm*pfi->gsiz;
991     }else {                                     
992       acum = acum + (levs*pfi->gsiz);
993     }
994
995 /*mf --------------mf*/
996 /*
997    time chunk header; the default is 0
998 */
999     if(pfi->seqflg && pfi->thdr>0) {
1000       pfi->thdr+=2;
1001     }
1002     pfi->tsiz = acum + pfi->thdr;
1003
1004 /*mf --------------mf*/
1005
1006     pfi->trecs = recacm;
1007     if (pfi->seqflg) pfi->tsiz-=1;
1008     pfi->tsiz += trlb;
1009
1010 /*------------------- non grid data???? -------- */
1011
1012   } else {
1013
1014     for (i=0; i<pfi->vnum; i++) {
1015       if (pvar->levels!=0) break;
1016       pvar->offset = i;
1017       pvar++;
1018     }
1019     for (j=i; j<pfi->vnum; j++) {
1020       if (pvar->levels==0) {
1021         gaprnt (0,"Open Error: Variables out of order\n");
1022         gaprnt (0,"  Non-vertical variables must go first\n");
1023         goto retrn;
1024       }
1025       pvar->offset = j-i;
1026       pvar++;
1027     }
1028     pfi->lvnum = pfi->vnum - i;
1029     pfi->ivnum = i;
1030   }
1031
1032 /*mf---
1033
1034   961204
1035
1036   set the global calendar and check if we are trying to change with a new file...
1037   we do this here to set the calandar for templating
1038
1039 ----mf*/
1040
1041 /*    if(mfcmn.cal365<0) { */
1042 /*      mfcmn.cal365=pfi->calendar; */
1043 /*    } else { */
1044 /*      if(pfi->calendar != mfcmn.cal365) { */
1045 /*        gaprnt(0,"Attempt to change the global calendar...\n"); */
1046 /*        if(mfcmn.cal365) { */
1047 /*      gaprnt(0,"The calendar is NOW 365 DAYS and you attempted to open a standard calendar file\n"); */
1048 /*        } else { */
1049 /*      gaprnt(0,"The calendar is NOW STANDARD and you attempted to open a 365-day calendar file\n"); */
1050 /*        } */
1051 /*        goto retrn; */
1052 /*      } */
1053 /*    } */
1054
1055   /* Allocate an I/O buffer the size of one row */
1056
1057   if (pfi->type > 1) {
1058     size = maxlv * sizeof(float);
1059   } else {
1060     size = pfi->dnum[0] * sizeof(float);
1061   }
1062   pfi->rbuf = (float *)malloc(size);
1063   if (pfi->idxflg) pfi->pbuf = (char *)malloc(size);
1064
1065   /* If a pre-projected grid, set up the interpolation
1066      constants.  */
1067
1068   if (pfi->ppflag) {
1069     rc = gappcn(pfi,pdefop1,pdefop2);
1070     if (rc) goto retrn;
1071   }
1072
1073   /* If the file name is a time series template, figure out
1074      which times go with which files, so we don't waste a lot
1075      of time later opening and closing files unnecessarily. */
1076
1077   if (pfi->tmplat) {
1078     pfi->fnums = (int *)malloc(sizeof(int)*pfi->dnum[3]);
1079     if (pfi->fnums==NULL) goto err8;
1080     j = 1;
1081     gr2t(pfi->grvals[3],1.0,&tdefi);
1082     ch = gafndt(pfi->name,&tdefi,&tdefi,pfi->abvals[3]);
1083     if (ch==NULL) goto err8;
1084     *(pfi->fnums) = j;
1085     for (i=2; i<=pfi->dnum[3]; i++) {
1086       gr2t(pfi->grvals[3],(float)i,&tdef);
1087       pos = gafndt(pfi->name,&tdef,&tdefi,pfi->abvals[3]);
1088       if (pos==NULL) goto err8;
1089       if (strcmp(ch,pos)!=0) {
1090         j = i;
1091         free(ch);
1092         ch = pos;
1093       }
1094       else{
1095         free(pos);
1096       }
1097       *(pfi->fnums+i-1) = j;
1098     }
1099     free(ch);
1100     pfi->fnumc = 0;
1101   }
1102
1103   fclose (descr);
1104   if (pdfi) fclose(pdfi);
1105
1106   return(0);
1107
1108  errm:
1109   gaprnt(0,"Open Error: Invalid pdef record.\n");
1110   pfi->ppflag = 0;
1111   goto err9;
1112
1113  err1:
1114   gaprnt (0,"Open Error:  Missing or invalid dimension size.\n");
1115   goto err9;
1116
1117  err2:
1118   gaprnt (0,"Open Error:  Missing or invalid dimension");
1119   gaprnt (0," scaling type\n");
1120   goto err9;
1121
1122  err3:
1123   gaprnt (0,"Open Error:  Missing or invalid dimension");
1124   gaprnt (0," starting value\n");
1125   goto err9;
1126
1127  err4:
1128   gaprnt (0,"Open Error:  Missing or invalid dimension");
1129   gaprnt (0," increment value\n");
1130   goto err9;
1131
1132  err4a:
1133   gaprnt (0,"Open Error:  0 time increment in tdef\n");
1134   gaprnt (0," use 1 for single time data\n");
1135   goto err9;
1136
1137  err5:
1138   gaprnt (0,"Open Error:  Missing or invalid variable");
1139   gaprnt (0," count\n");
1140   goto err9;
1141
1142  err6:
1143   gaprnt (0,"Open Error:  Invalid variable record\n");
1144   goto err9;
1145
1146  err7:
1147   gaprnt (0,"Open Error:  Invalid number of levels\n");
1148   goto err9;
1149
1150  err8:
1151   gaprnt (0,"Open Error:  Memory allocation Error\n");
1152   goto retrn;
1153
1154  err9:
1155   gaprnt (0,"  --> The invalid description file record is: \n");
1156   gaprnt (0,"  --> ");
1157   gaprnt (0,rec);
1158   gaprnt (0,"\n");
1159
1160  retrn:
1161   gaprnt (0,"  The data file was not opened. \n");
1162   fclose (descr);
1163   if (mflflg) fclose(mfile);
1164   if (pdfi) fclose(pdfi);
1165   return(1);
1166
1167 }
1168
1169
1170
1171 /* Process linear scaling args */
1172
1173 int deflin (char *ch, struct gafile *pfi, int dim, int flag) {
1174 float *vals,v1,v2;
1175
1176   vals = (float *)malloc(sizeof(float)*6);
1177   if (vals==NULL) return (-1);
1178
1179   if ( (ch = nxtwrd(ch))==NULL) goto err1;
1180   if ( valprs(ch,&v1)==NULL) goto err1;
1181   if (flag) v2 = 1.0;
1182   else {
1183     if ( (ch = nxtwrd(ch))==NULL) goto err2;
1184     if ( valprs(ch,&v2)==NULL) goto err2;
1185   }
1186   if (dim<2 && v2<=0.0) goto err2;
1187   *(vals+1) = v1 - v2;
1188   *(vals) = v2;
1189   *(vals+2) = -999.9;
1190   pfi->grvals[dim] = vals;
1191   *(vals+4) = -1.0 * ( (v1-v2)/v2 );
1192   *(vals+3) = 1.0/v2;
1193   *(vals+5) = -999.9;
1194   pfi->abvals[dim] = vals+3;
1195   pfi->ab2gr[dim] = liconv;
1196   pfi->gr2ab[dim] = liconv;
1197   pfi->linear[dim] = 1;
1198   return (0);
1199
1200 err1:
1201   gaprnt (0,"Open Error:  Missing or invalid dimension");
1202   gaprnt (0," starting value\n");
1203   free (vals);
1204   return (1);
1205
1206 err2:
1207   gaprnt (0,"Open Error:  Missing or invalid dimension");
1208   gaprnt (0," increment value\n");
1209   free (vals);
1210   return (1);
1211 }
1212
1213 /* Process levels values in def record */
1214 /* Return codes:  -1 is memory allocation error, 1 is other error */
1215
1216 int deflev (char *ch, char *rec, struct gafile *pfi, int dim) {
1217 float *vvs,*vals,v1,v2;
1218 int i;
1219
1220   if (pfi->dnum[dim]==1) {
1221     i = deflin (ch, pfi, dim, 1);
1222     return (i);
1223   }
1224
1225   vals = (float *)malloc((pfi->dnum[dim]+5)*sizeof(float));
1226   if (vals==NULL) return (-1);
1227
1228   vvs = vals;
1229   *vvs = (float)pfi->dnum[dim];
1230   vvs++;
1231   for (i=0; i<pfi->dnum[dim]; i++) {
1232     if ( (ch = nxtwrd(ch))==NULL) {
1233       if (fgets(rec,256,descr)==NULL) goto err2;
1234       if (nxtwrd(rec)==NULL) goto err3;
1235       ch = rec;
1236       while (*ch==' ') ch++;
1237     }
1238     if (valprs(ch,&v1)==NULL) goto err1;
1239     *vvs = v1;
1240     vvs++;
1241   }
1242   *vvs = -999.9;
1243   pfi->abvals[dim] = vals;
1244   pfi->grvals[dim] = vals;
1245   pfi->ab2gr[dim] = lev2gr;
1246   pfi->gr2ab[dim] = gr2lev;
1247   pfi->linear[dim] = 0;
1248   return (0);
1249
1250 err1:
1251   gaprnt (0,"Open Error:  Invalid value in LEVELS data\n");
1252   free (vals);
1253   return (1);
1254
1255 err2:
1256   gaprnt (0,"Open Error:  Unexpected EOF reading descriptor file\n");
1257   gaprnt (0,"   EOF occurred reading LEVELS values\n");
1258   free (vals);
1259   return (1);
1260
1261 err3:
1262   gaprnt (0,"Open Error:  Blank Record found in LEVELS data\n");
1263   free (vals);
1264   return (1);
1265 }
1266
1267 /* Allocate and initialize a gafile structure */
1268
1269 struct gafile *getpfi (void) {
1270 struct gafile *pfi;
1271 int i;
1272 /* #ifdef USESDF */
1273 /* int init_io_std(IO_STD**) ; */
1274 /* #endif */
1275
1276   pfi = (struct gafile *)malloc(sizeof(struct gafile));
1277   if (pfi==NULL) return (NULL);
1278
1279   pfi->type = 1;        /* Assume grid unless told otherwise */
1280   pfi->tlpflg = 0;      /* Assume file not circular */
1281   pfi->bswap = 0;       /* Assume no byte swapping needed */
1282   pfi->seqflg = 0;      /* Assume direct access */
1283   pfi->yrflg = 0;       /* Assume south to north */
1284   pfi->zrflg = 0;       /* Assume bottom to top */
1285   pfi->idxflg = 0;      /* Assume binary */
1286   pfi->fhdr = 0;        /* Assume no file header */
1287   pfi->thdr=0;          /*mf assume no time header mf*/
1288   pfi->xyhdr=0;         /*mf assume no xyheader mf*/
1289   pfi->pindx = NULL;
1290   pfi->rbuf = NULL;
1291   pfi->pbuf = NULL;
1292   pfi->wrap = 0;        /* Assume no wrapping */
1293   for (i=0; i<4; i++) pfi->dimoff[i] = 0;
1294   pfi->title[0] = '\0';
1295   pfi->infile = NULL;
1296   pfi->pvar1 = NULL;
1297   pfi->tstrt = NULL;
1298   pfi->tcnt = NULL;
1299   pfi->grvals[0] = NULL;
1300   pfi->grvals[1] = NULL;
1301   pfi->grvals[2] = NULL;
1302   pfi->grvals[3] = NULL;
1303   pfi->grbgrd = -999;
1304   pfi->tmplat = 0;
1305   pfi->tempname = NULL;
1306   pfi->fnums = NULL;
1307   pfi->infile = NULL;
1308   pfi->mnam = NULL;
1309   pfi->errcnt = 0;
1310   pfi->errflg = 0;
1311   pfi->ppflag = 0;  /* Assume lat-lon grid */
1312   pfi->ppwrot = 0;  /* Assume no wind rotataion */
1313   for (i=0; i<8; i++) pfi->ppi[i] = NULL;
1314   for (i=0; i<8; i++) pfi->ppf[i] = NULL;
1315   pfi->ppw = NULL;
1316 #if USESDF == 1
1317   pfi->sdf_ptr = NULL ;
1318 /*  if (!init_io_std(&(pfi->sdf_ptr))) { */
1319 /*    gaprnt(0, */
1320 /* "Initialize file error:  Couldn't allocate and initialize SDF structure.\n") ; */
1321 /*    return(NULL) ; */
1322 /*  } */
1323 #endif
1324
1325   return (pfi);
1326 }
1327
1328 /* Free a gafile structure and associated storage.  If the flag is
1329    true, DO NOT free the storage related to scaling transforms,
1330    since someone, somewhere,  may still be pointing to that. */
1331
1332 void frepfi (struct gafile *pfi, int flag) {
1333 struct gaindx *pindx;
1334 int i;
1335 #if USESDF == 1
1336 void free_io_std(IO_STD**) ;
1337 #endif
1338
1339   if (pfi->pindx) {
1340     pindx = pfi->pindx;
1341     if (pindx->hipnt) free(pindx->hipnt);
1342     if (pindx->hfpnt) free(pindx->hfpnt);
1343     if (pindx->intpnt) free(pindx->intpnt);
1344     if (pindx->fltpnt) free(pindx->fltpnt);
1345     free (pindx);
1346   }
1347   if (pfi->fnums) free(pfi->fnums);
1348   if (pfi->tstrt) free(pfi->tstrt);
1349   if (pfi->tcnt) free(pfi->tcnt);
1350   if (pfi->pvar1) free(pfi->pvar1);
1351   if (pfi->rbuf) free(pfi->rbuf);
1352   if (pfi->pbuf) free(pfi->pbuf);
1353   if (pfi->mnam) free(pfi->mnam);
1354   if (pfi->tempname!=NULL) {
1355           free(pfi->tempname);
1356           pfi->tempname=NULL;
1357   }
1358   for (i=0; i<8; i++) if (pfi->ppi[i]) free(pfi->ppi[i]);
1359   for (i=0; i<8; i++) if (pfi->ppf[i]) free(pfi->ppf[i]);
1360   if (!flag) {
1361     for (i=0; i<4; i++) if (pfi->grvals[i]) free(pfi->grvals[i]);
1362   }
1363 #if USESDF == 1
1364   if (pfi->sdf_ptr) {
1365     free_io_std(&(pfi->sdf_ptr)) ;
1366   }
1367 #endif
1368   free (pfi);
1369 }
1370
1371 /* Routine to calculate or input the interpolation constants needed for
1372    the implicit interpolation from pre-projected grids to lat-lon. */
1373
1374 int gappcn (struct gafile *pfi, int pdefop1, int pdefop2) {
1375 FILE *pdfi;
1376 int size,i,j,ii,jj;
1377 float lat,lon,rii,rjj;
1378 float *dx, *dy, *etarot;
1379 int *ioff, rdw, rc, pnum;
1380
1381   size = pfi->dnum[0]*pfi->dnum[1];
1382
1383   if (pfi->ppflag != 8) {
1384
1385     /* Allocate space needed for the grids of interpolation constants */
1386
1387     pfi->ppi[0] = (int *)malloc(sizeof(int)*size);
1388     if (pfi->ppi[0]==NULL) goto merr;
1389     pfi->ppf[0] = (float *)malloc(sizeof(float)*size);
1390     if (pfi->ppf[0]==NULL) goto merr;
1391     pfi->ppf[1] = (float *)malloc(sizeof(float)*size);
1392     if (pfi->ppf[1]==NULL) goto merr;
1393     if (pfi->ppwrot) {
1394       pfi->ppw = (float *)malloc(sizeof(float)*size);
1395       if (pfi->ppw==NULL) goto merr;
1396     }
1397   }
1398
1399   if (pfi->ppflag==7) {
1400     pfi->ppi[1] = (int *)malloc(sizeof(int)*size);
1401     if (pfi->ppi[1]==NULL) goto merr;
1402     if (pdefop1==2) {
1403       rc = fread(&rdw, sizeof(int), 1, pdfi);
1404       if (rc!=1) goto merr2;
1405     }
1406     rc = fread(pfi->ppf[0], sizeof(float), size, pdfi);
1407     if (rc!=size) goto merr2;
1408     if (pdefop1==2) {
1409       rc = fread(&rdw, sizeof(int), 1, pdfi);
1410       if (rc!=1) goto merr2;
1411       rc = fread(&rdw, sizeof(int), 1, pdfi);
1412       if (rc!=1) goto merr2;
1413     }
1414     rc = fread(pfi->ppf[1], sizeof(float), size, pdfi);
1415     if (rc!=size) goto merr2;
1416     if (pdefop1==2) {
1417       rc = fread(&rdw, sizeof(int), 1, pdfi);
1418       if (rc!=1) goto merr2;
1419       rc = fread(&rdw, sizeof(int), 1, pdfi);
1420       if (rc!=1) goto merr2;
1421     }
1422     rc = fread(pfi->ppw, sizeof(float), size, pdfi);
1423     if (rc!=size) goto merr2;
1424
1425     if (  (pdefop2==2 && !BYTEORDER) ||
1426           (pdefop2==3 && BYTEORDER) ) {
1427       gabswp (pfi->ppf[0],size);
1428       gabswp (pfi->ppf[1],size);
1429       gabswp (pfi->ppw,size);
1430     }
1431
1432     ioff = pfi->ppi[0];
1433     dx = pfi->ppf[0];
1434     dy = pfi->ppf[1];
1435     for (j=0; j<pfi->dnum[1]; j++) {
1436       for (i=0; i<pfi->dnum[0]; i++) {
1437         if (*dx < 0.0) *ioff = -1;
1438         else {
1439           ii = (int)(*dx);
1440           jj = (int)(*dy);
1441           *dx = *dx - (float)ii;
1442           *dy = *dy - (float)jj;
1443           if (ii<1 || ii>pfi->ppisiz-1 || jj<1 || jj>pfi->ppjsiz-1) {
1444             *ioff = -1;
1445           } else {
1446             *ioff = (jj-1)*pfi->ppisiz + ii - 1;
1447           }
1448           ioff++; dx++; dy++;
1449         }
1450       }
1451     }
1452
1453   /* When pdef is a file, read in the offsets of the points
1454      to use and their weights, as well as the array of
1455      wind rotation values to use */
1456
1457   } else if (pfi->ppflag==8) {
1458     pnum = (int)(pfi->ppvals[0]+0.1);
1459     for (i=0; i<pnum; i++) {
1460       pfi->ppi[i] = (int *)malloc(sizeof(int)*size);
1461       if (pfi->ppi[i]==NULL) goto merr;
1462       if (pdefop1==2) {
1463         rc = fread(&rdw, sizeof(int), 1, pdfi);
1464         if (rc!=1) goto merr2;
1465       }
1466       rc = fread(pfi->ppi[i], sizeof(int), size, pdfi);
1467       if (rc!=size) goto merr2;
1468       if (pdefop1==2) {
1469         rc = fread(&rdw, sizeof(int), 1, pdfi);
1470         if (rc!=1) goto merr2;
1471       }
1472       pfi->ppf[i] = (float *)malloc(sizeof(int)*size);
1473       if (pfi->ppf[i]==NULL) goto merr;
1474       if (pdefop1==2) {
1475         rc = fread(&rdw, sizeof(int), 1, pdfi);
1476         if (rc!=1) goto merr2;
1477       }
1478       rc = fread(pfi->ppf[i], sizeof(float), size, pdfi);
1479       if (rc!=size) goto merr2;
1480       if (pdefop1==2) {
1481         rc = fread(&rdw, sizeof(int), 1, pdfi);
1482         if (rc!=1) goto merr2;
1483       }
1484       if (  (pdefop2==2 && !BYTEORDER) ||
1485             (pdefop2==3 && BYTEORDER) ) {
1486         gabswp ((float *)(pfi->ppi[i]),size);
1487         gabswp (pfi->ppf[i],size);
1488       }
1489     }
1490     pfi->ppw = (float *)malloc(sizeof(float)*size);
1491     if (pfi->ppw==NULL) goto merr;
1492     if (pdefop1==2) {
1493       rc = fread(&rdw, sizeof(int), 1, pdfi);
1494       if (rc!=1) goto merr2;
1495     }
1496     rc = fread(pfi->ppw, sizeof(float), size, pdfi);
1497     if (rc!=size) goto merr2;
1498
1499   /* We calculate three constants at each lat-lon grid point:
1500      offset of the ij gridpoint, and the delta x and delta y
1501      values. */
1502
1503   } else {
1504     ioff = pfi->ppi[0];
1505     dx = pfi->ppf[0];
1506     dy = pfi->ppf[1];
1507     if ( pfi->ppflag == 4) etarot=pfi->ppw;
1508
1509     for (j=0; j<pfi->dnum[1]; j++) {
1510       lat = pfi->gr2ab[1](pfi->grvals[1],(float)(j+1));
1511       for (i=0; i<pfi->dnum[0]; i++) {
1512         lon = pfi->gr2ab[0](pfi->grvals[0],(float)(i+1));
1513         if (pfi->ppflag==3) {
1514           ll2lc (pfi->ppvals, lat, lon, &rii, &rjj);
1515         } else if (pfi->ppflag==4) {
1516           ll2eg (pfi->ppisiz,pfi->ppjsiz,pfi->ppvals, lon, lat, &rii, &rjj, etarot);
1517         } else if (pfi->ppflag==5) {
1518           ll2pse (pfi->ppisiz,pfi->ppjsiz,pfi->ppvals, lon, lat, &rii, &rjj);
1519         } else if (pfi->ppflag==6) {
1520           ll2ops (pfi->ppvals, lon, lat, &rii, &rjj);
1521         } else {
1522           w3fb04(lat, -1.0*lon, pfi->ppvals[3], -1.0*pfi->ppvals[2], &rii, &rjj);
1523           rii = rii + pfi->ppvals[0];
1524           rjj = rjj + pfi->ppvals[1];
1525         }
1526         ii = (int)rii;
1527         jj = (int)rjj;
1528         *dx = rii - (float)ii;
1529         *dy = rjj - (float)jj;
1530         if (ii<1 || ii>pfi->ppisiz-1 || jj<1 || jj>pfi->ppjsiz-1) {
1531           *ioff = -1;
1532         } else {
1533           *ioff = (jj-1)*pfi->ppisiz + ii - 1;
1534         }
1535         ioff++; dx++; dy++;
1536
1537         if ( pfi->ppflag == 4) etarot++;
1538
1539       }
1540     }
1541   }
1542   return(0);
1543
1544 merr:
1545   gaprnt (0,"Open Error:  Memory allocation error in pdef handler\n");
1546   return(1);
1547
1548 merr2:
1549   gaprnt (0,"Open Error:  I/O Error on pdef file read\n");
1550   return(1);
1551
1552 }
1553
1554
1555 void w3fb04 (float alat, float along, float xmeshl, float orient,
1556      float *xi, float *xj) {
1557
1558 /*
1559 C
1560 C SUBPROGRAM: W3FB04         LATITUDE, LONGITUDE TO GRID COORDINATES
1561 C   AUTHOR: MCDONELL,J.      ORG: W345       DATE: 90-06-04
1562 C
1563 C ABSTRACT: CONVERTS THE COORDINATES OF A LOCATION ON EARTH FROM THE
1564 C   NATURAL COORDINATE SYSTEM OF LATITUDE/LONGITUDE TO THE GRID (I,J)
1565 C   COORDINATE SYSTEM OVERLAID ON A POLAR STEREOGRAPHIC MAP PRO-
1566 C   JECTION TRUE AT 60 DEGREES N OR S LATITUDE. W3FB04 IS THE REVERSE
1567 C   OF W3FB05.
1568 C
1569 C PROGRAM HISTORY LOG:
1570 C   77-05-01  J. MCDONELL
1571 C   89-01-10  R.E.JONES   CONVERT TO MICROSOFT FORTRAN 4.1
1572 C   90-06-04  R.E.JONES   CONVERT TO SUN FORTRAN 1.3
1573 C   93-01-26  B. Doty     converted to C
1574 C
1575 C USAGE:  CALL W3FB04 (ALAT, ALONG, XMESHL, ORIENT, XI, XJ)
1576 C
1577 C   INPUT VARIABLES:
1578 C     NAMES  INTERFACE DESCRIPTION OF VARIABLES AND TYPES
1579 C     ------ --------- -----------------------------------------------
1580 C     ALAT   ARG LIST  LATITUDE IN DEGREES (<0 IF SH)
1581 C     ALONG  ARG LIST  WEST LONGITUDE IN DEGREES
1582 C     XMESHL ARG LIST  MESH LENGTH OF GRID IN KM AT 60 DEG LAT(<0 IF SH)
1583 C                   (190.5 LFM GRID, 381.0 NH PE GRID,-381.0 SH PE GRID)
1584 C     ORIENT ARG LIST  ORIENTATION WEST LONGITUDE OF THE GRID
1585 C                   (105.0 LFM GRID, 80.0 NH PE GRID, 260.0 SH PE GRID)
1586 C
1587 C   OUTPUT VARIABLES:
1588 C     NAMES  INTERFACE DESCRIPTION OF VARIABLES AND TYPES
1589 C     ------ --------- -----------------------------------------------
1590 C     XI     ARG LIST  I OF THE POINT RELATIVE TO NORTH OR SOUTH POLE
1591 C     XJ     ARG LIST  J OF THE POINT RELATIVE TO NORTH OR SOUTH POLE
1592 C
1593 C   SUBPROGRAMS CALLED:
1594 C     NAMES                                                   LIBRARY
1595 C     ------------------------------------------------------- --------
1596 C     COS SIN                                                 SYSLIB
1597 C
1598 C   REMARKS: ALL PARAMETERS IN THE CALLING STATEMENT MUST BE
1599 C     REAL. THE RANGE OF ALLOWABLE LATITUDES IS FROM A POLE TO
1600 C     30 DEGREES INTO THE OPPOSITE HEMISPHERE.
1601 C     THE GRID USED IN THIS SUBROUTINE HAS ITS ORIGIN (I=0,J=0)
1602 C     AT THE POLE IN EITHER HEMISPHERE, SO IF THE USER'S GRID HAS ITS
1603 C     ORIGIN AT A POINT OTHER THAN THE POLE, A TRANSLATION IS NEEDED
1604 C     TO GET I AND J. THE GRIDLINES OF I=CONSTANT ARE PARALLEL TO A
1605 C     LONGITUDE DESIGNATED BY THE USER. THE EARTH'S RADIUS IS TAKEN
1606 C     TO BE 6371.2 KM.
1607 C
1608 C ATTRIBUTES:
1609 C   LANGUAGE: SUN FORTRAN 1.4
1610 C   MACHINE:  SUN SPARCSTATION 1+
1611 C*/
1612
1613 static float radpd = 0.01745329;
1614 static float earthr = 6371.2;
1615
1616 float re,xlat,wlong,r;
1617
1618       re    = (earthr * 1.86603) / xmeshl;
1619       xlat =  alat * radpd;
1620
1621       if (xmeshl>0.0) {
1622         wlong = (along + 180.0 - orient) * radpd;
1623         r     = (re * cos(xlat)) / (1.0 + sin(xlat));
1624         *xi    = r * sin(wlong);
1625         *xj    = r * cos(wlong);
1626
1627       } else {
1628
1629         re    = -re;
1630         xlat =  -xlat;
1631         wlong = (along - orient) * radpd;
1632         r     = (re * cos(xlat)) / (1.0+ sin(xlat));
1633         *xi   =  r * sin(wlong);
1634         *xj   = -r * cos(wlong);
1635       }
1636 }
1637
1638 /* Lambert conformal conversion */
1639
1640 void ll2lc (float *vals, float grdlat, float grdlon,
1641                                  float *grdi, float *grdj) {
1642
1643 /*  Subroutine to convert from lat-lon to lambert conformal i,j.
1644     Provided by NRL Monterey; converted to C 6/15/94.
1645
1646 c          SUBROUTINE: ll2lc
1647 c
1648 c          PURPOSE: To compute i- and j-coordinates of a specified
1649 c                   grid given the latitude and longitude points.
1650 c                   All latitudes in this routine start
1651 c                   with -90.0 at the south pole and increase
1652 c                   northward to +90.0 at the north pole.  The
1653 c                   longitudes start with 0.0 at the Greenwich
1654 c                   meridian and increase to the east, so that
1655 c                   90.0 refers to 90.0E, 180.0 is the inter-
1656 c                   national dateline and 270.0 is 90.0W.
1657 c
1658 c          INPUT VARIABLES:
1659 c
1660 c  vals+0    reflat: latitude at reference point (iref,jref)
1661 c
1662 c  vals+1    reflon: longitude at reference point (iref,jref)
1663 c
1664 c  vals+2    iref:   i-coordinate value of reference point
1665 c
1666 c  vals+3    jref:   j-coordinate value of reference point
1667 c
1668 c  vals+4    stdlt1: standard latitude of grid
1669 c
1670 c  vals+5    stdlt2: second standard latitude of grid (only required
1671 c                    if igrid = 2, lambert conformal)
1672 c
1673 c  vals+6    stdlon: standard longitude of grid (longitude that
1674 c                     points to the north)
1675 c
1676 c  vals+7    delx:   grid spacing of grid in x-direction
1677 c                    for igrid = 1,2,3 or 4, delx must be in meters
1678 c                    for igrid = 5, delx must be in degrees
1679 c
1680 c  vals+8    dely:   grid spacing (in meters) of grid in y-direction
1681 c                    for igrid = 1,2,3 or 4, delx must be in meters
1682 c                    for igrid = 5, dely must be in degrees
1683 c
1684 c            grdlat: latitude of point (grdi,grdj)
1685 c
1686 c            grdlon: longitude of point (grdi,grdj)
1687 c
1688 c            grdi:   i-coordinate(s) that this routine will generate
1689 c                    information for
1690 c
1691 c            grdj:   j-coordinate(s) that this routine will generate
1692 c                    information for
1693 c
1694 */
1695
1696   float pi, pi2, pi4, d2r, r2d, radius, omega4;
1697   float gcon,ogcon,ahem,deg,cn1,cn2,cn3,cn4,rih,xih,yih,rrih,check;
1698   float alnfix,alon,x,y;
1699
1700   pi = 4.0*atan(1.0);
1701   pi2 = pi/2.0;
1702   pi4 = pi/4.0;
1703   d2r = pi/180.0;
1704   r2d = 180.0/pi;
1705   radius = 6371229.0;
1706   omega4 = 4.0*pi/86400.0;
1707
1708 /*mf -------------- mf*/
1709 /*case where standard lats are the same */
1710
1711   if(*(vals+4) == *(vals+5)) {
1712     gcon = sin(*(vals+4)*d2r);
1713   } else {
1714     gcon = (log(sin((90.0-*(vals+4))*d2r))
1715             -log(sin((90.0-*(vals+5))*d2r)))
1716       /(log(tan((90.0-*(vals+4))*0.5*d2r))
1717         -log(tan((90.0-*(vals+5))*0.5*d2r)));
1718   }
1719 /*mf -------------- mf*/
1720   ogcon = 1.0/gcon;
1721   ahem = fabs(*(vals+4))/(*(vals+4));
1722   deg = (90.0-fabs(*(vals+4)))*d2r;
1723   cn1 = sin(deg);
1724   cn2 = radius*cn1*ogcon;
1725   deg = deg*0.5;
1726   cn3 = tan(deg);
1727   deg = (90.0-fabs(*vals))*0.5*d2r;
1728   cn4 = tan(deg);
1729   rih = cn2*pow((cn4/cn3),gcon);
1730   deg = (*(vals+1)-*(vals+6))*d2r*gcon;
1731   xih = rih*sin(deg);
1732   yih = -rih*cos(deg)*ahem;
1733   deg = (90.0-grdlat*ahem)*0.5*d2r;
1734   cn4 = tan(deg);
1735   rrih = cn2*pow((cn4/cn3),gcon);
1736   check = 180.0-*(vals+6);
1737   alnfix = *(vals+6)+check;
1738   alon = grdlon+check;
1739   while (alon<0.0) alon = alon+360.0;
1740   while (alon>360.0) alon = alon-360.0;
1741   deg = (alon-alnfix)*gcon*d2r;
1742   x = rrih*sin(deg);
1743   y = -rrih*cos(deg)*ahem;
1744   *grdi = *(vals+2)+(x-xih)/(*(vals+7));
1745   *grdj = *(vals+3)+(y-yih)/(*(vals+8));
1746 }
1747
1748 /* NMC eta ll to xy map  */
1749
1750 void ll2eg (int im, int jm, float *vals,  float grdlon, float grdlat,
1751             float *grdi, float *grdj, float *alpha) {
1752
1753 /*  Subroutine to convert from lat-lon to NMC eta i,j.
1754
1755     Provided by Eric Rogers NMC; converted to C 3/29/95 by Mike Fiorino.
1756
1757 c          SUBROUTINE: ll2eg
1758 c
1759 c          PURPOSE: To compute i- and j-coordinates of a specified
1760 c                   grid given the latitude and longitude points.
1761 c                   All latitudes in this routine start
1762 c                   with -90.0 at the south pole and increase
1763 c                   northward to +90.0 at the north pole.  The
1764 c                   longitudes start with 0.0 at the Greenwich
1765 c                   meridian and increase to the east, so that
1766 c                   90.0 refers to 90.0E, 180.0 is the inter-
1767 c                   national dateline and 270.0 is 90.0W.
1768 c
1769 c          INPUT VARIABLES:
1770 c
1771 c  vals+0    tlm0d: longitude of the reference center point
1772 c
1773 c  vals+1    tph0d: latitude of the reference center point
1774 c
1775 c  vals+2    dlam:  dlon grid increment in deg
1776 c
1777 c  vals+3    dphi:  dlat grid increment in deg
1778 c
1779 c
1780 c            grdlat: latitude of point (grdi,grdj)
1781 c
1782 c            grdlon: longitude of point (grdi,grdj)
1783 c
1784 c            grdi:   i-coordinate(s) that this routine will generate
1785 c                    information for
1786 c
1787 c            grdj:   j-coordinate(s) that this routine will generate
1788 c                    information for
1789 c
1790
1791 */
1792
1793   float pi,d2r,r2d, earthr;
1794   float tlm0d,tph0d,dlam,dphi;
1795   float phi,lam,lame,lam0,phi0,lam0e,cosphi,sinphi,sinphi0,cosphi0,sinlamr,coslamr;
1796   float x1,x,y,z,bigphi,biglam,cc,num,den,tlm,tph;
1797
1798   int idim,jdim;
1799
1800   pi=3.141592654;
1801
1802   d2r=pi/180.0;
1803   r2d=1.0/d2r;
1804   earthr=6371.2;
1805
1806   tlm0d=-*(vals+0); /* convert + W to + E, the grads standard for longitude */
1807   tph0d=*(vals+1);
1808   dlam=(*(vals+2))*0.5;
1809   dphi=(*(vals+3))*0.5;
1810
1811   /* grid point and center of eta grid trig */
1812
1813   /* convert to radians */
1814
1815   phi    = grdlat*d2r;
1816   lam    = -grdlon*d2r; /* convert + W to + E, the grads standard for longitude */
1817   lame   = (grdlon)*d2r;
1818
1819   phi0   = tph0d*d2r;
1820   lam0   = tlm0d*d2r;
1821   lam0e  = ( 360.0 + *(vals+0) )*d2r;
1822
1823   /* cos and sin */
1824
1825   cosphi = cos(phi);
1826   sinphi = sin(phi);
1827
1828   sinphi0 = sin(phi0);
1829   cosphi0 = cos(phi0);
1830
1831   sinlamr=sin(lame-lam0e);
1832   coslamr=cos(lame-lam0e);
1833
1834   x1     = cosphi*cos(lam-lam0);
1835   x      = cosphi0*x1+sinphi0*sinphi;
1836   y      = -cosphi*sin(lam-lam0);
1837   z      = -sinphi0*x1+cosphi0*sinphi;
1838
1839   /* params for wind rotation alpha */
1840
1841   cc=cosphi*coslamr;
1842   num=cosphi*sinlamr;
1843   den=cosphi0*cc+sinphi0*sinphi;
1844
1845   tlm=atan2(num,den);
1846
1847
1848   /* parms for lat/lon -> i,j */
1849
1850   bigphi = atan(z/(sqrt(x*x+y*y)))*r2d;
1851   biglam = atan(y/x)*r2d;
1852
1853   idim = im*2-1;
1854   jdim = jm*2-1 ;
1855
1856   *grdi  = (biglam/dlam)+(idim+1)*0.5;
1857   *grdj  = (bigphi/dphi)+(jdim+1)*0.5;
1858   *grdi  = (*grdi+1)*0.5-1;
1859   *grdj  = (*grdj+1)*0.5-1;
1860
1861   *alpha = asin( ( sinphi0*sin(tlm)) / cosphi ) ;
1862
1863 /*
1864   printf("ddd %6.2f %6.2f %6.2f %6.2f %g %g %g %g\n",
1865     grdlon,grdlat,*grdi,*grdj,*alpha,tlm*r2d,cosphi,sinphi0);
1866 */
1867
1868 }
1869
1870 void ll2pse (int im, int jm, float *vals, float lon, float lat,
1871              float *grdi, float *grdj) {
1872
1873
1874   /* Convert from geodetic latitude and longitude to polar stereographic
1875      grid coordinates.  Follows mapll by V. J. Troisi.         */
1876   /* Conventions include that slat and lat must be absolute values */
1877   /* The hemispheres are controlled by the sgn parameter */
1878   /* Bob Grumbine 15 April 1994. */
1879
1880   const float rearth = 6378.273e3;
1881   const float eccen2 = 0.006693883;
1882   const float pi = 3.141592654;
1883
1884   float cdr, alat, along, e, e2;
1885   float t, x, y, rho, sl, tc, mc;
1886   float slat,slon,xorig,yorig,sgn,polei,polej,dx,dy;
1887
1888   slat=*(vals+0);
1889   slon=*(vals+1);
1890   polei=*(vals+2);
1891   polej=*(vals+3);
1892   dx=*(vals+4)*1000;
1893   dy=*(vals+5)*1000;
1894   sgn=*(vals+6);
1895
1896
1897   xorig = -polei*dx;
1898   yorig = -polej*dy;
1899
1900   /*printf("ppp %g %g %g %g %g %g %g\n",slat,slon,polei,polej,dx,dy,sgn);*/
1901
1902   cdr   = 180./pi;
1903   alat  = lat/cdr;
1904   along = lon/cdr;
1905   e2 = eccen2;
1906   e  = sqrt(eccen2);
1907
1908   if ( fabs(lat) > 90.)  {
1909     *grdi = -1;
1910     *grdj = -1;
1911     return;
1912   }
1913   else {
1914     t = tan(pi/4. - alat/2.) /
1915       pow( (1.-e*sin(alat))/(1.+e*sin(alat)) , e/2.);
1916
1917     if ( fabs(90. - slat) < 1.E-3) {
1918       rho = 2.*rearth*t/
1919         pow( pow(1.+e,1.+e) * pow(1.-e,1.-e) , e/2.);
1920     }
1921     else {
1922       sl = slat/cdr;
1923       tc = tan(pi/4.-sl/2.) /
1924         pow( (1.-e*sin(sl))/(1.+e*sin(sl)), (e/2.) );
1925       mc = cos(sl)/ sqrt(1.-e2*sin(sl)*sin(sl) );
1926       rho = rearth * mc*t/tc;
1927     }
1928
1929     x = rho*sgn*cos(sgn*(along+slon/cdr));
1930     y = rho*sgn*sin(sgn*(along+slon/cdr));
1931
1932     *grdi = (x - xorig)/dx+1;
1933     *grdj = (y - yorig)/dy+1;
1934
1935     /*printf("ppp (%g %g) (%g %g %g) %g %g\n",lat,lon,x,y,rho,*grdi,*grdj);*/
1936
1937     return;
1938   }
1939
1940 }
1941
1942 void ll2ops(float *vals, float lni, float lti, float *grdi, float *grdj) {
1943
1944   const float radius = 6371229.0 ;
1945   const float pi = 3.141592654;
1946
1947   float stdlat, stdlon, xref, yref, xiref, yjref, delx , dely;
1948
1949   float plt,pln;
1950   double pi180,c1,c2,c3,c4,c5,c6,arg2a,bb,plt1,alpha, pln1,plt90,argu1,argu2;
1951
1952   double hsign,glor,rstdlon,glolim,facpla,x,y;
1953
1954   stdlat = *(vals+0);
1955   stdlon = *(vals+1);
1956   xref = *(vals+2);
1957   yref = *(vals+3);
1958   xiref = *(vals+4);
1959   yjref = *(vals+5);
1960   delx = *(vals+6);
1961   dely = *(vals+7);
1962
1963   c1=1.0 ;
1964   pi180 = asin(c1)/90.0;
1965
1966 /*
1967 c
1968 c     set flag for n/s hemisphere and convert longitude to <0 ; 360> interval
1969 c
1970 */
1971   if(stdlat >= 0.0) {
1972     hsign= 1.0 ;
1973   } else {
1974     hsign=-1.0 ;
1975   }
1976 /*
1977 c
1978 c     set flag for n/s hemisphere and convert longitude to <0 ; 360> interval
1979 c
1980 */
1981   glor=lni ;
1982   if(glor <= 0.0) glor=360.0+glor ;
1983   rstdlon=stdlon;
1984   if(rstdlon < 0.0) rstdlon=360.0+stdlon;
1985
1986 /*
1987 c
1988 c     test for a n/s pole case
1989 c
1990 */
1991   if(stdlat == 90.0) {
1992     plt=lti ;
1993     pln=fmod(glor+270.0,360.0) ;
1994     goto l2000;
1995   }
1996
1997   if(stdlat == -90.0) {
1998     plt=-lti ;
1999     pln=fmod(glor+270.0,360.0) ;
2000     goto l2000;
2001   }
2002
2003
2004 /*
2005 c
2006 c     test for longitude on 'greenwich or date line'
2007 c
2008 */
2009   if(glor == rstdlon) {
2010     if(lti > stdlat) {
2011       plt=90.0-lti+stdlat;
2012       pln=90.0;
2013     } else {
2014       plt=90.0-stdlat+lti;
2015       pln=270.0;;
2016     }
2017     goto l2000;
2018   }
2019
2020   if(fmod(glor+180.0,360.0) == rstdlon) {
2021     plt=stdlat-90.0+lti;
2022     if(plt < -90.0) {
2023       plt=-180.0-plt;
2024       pln=270.0;
2025     } else {
2026       pln= 90.0;
2027     }
2028     goto l2000 ;
2029   }
2030
2031 /*
2032 c
2033 c     determine longitude distance relative to rstdlon so it belongs to
2034 c     the absolute interval 0 - 180
2035 c
2036 */
2037   argu1 = glor-rstdlon;
2038   if(argu1 > 180.0) argu1 = argu1-360.0;
2039   if(argu1 < -180.0) argu1 = argu1+360.0;
2040
2041 /*
2042 c
2043 c     1. get the help circle bb and angle alpha (legalize arguments)
2044 c
2045 */
2046
2047   c2=lti*pi180 ;
2048   c3=argu1*pi180 ;
2049   arg2a = cos(c2)*cos(c3) ;
2050   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = max1(arg2a,-c1)  */
2051   if(  c1 < arg2a ) arg2a = c1 ; /* min1(arg2a, c1)         */
2052   bb = acos(arg2a) ;
2053
2054   c4=hsign*lti*pi180 ;
2055   arg2a = sin(c4)/sin(bb) ;
2056   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = dmax1(arg2a,-c1) */
2057   if(  c1 < arg2a ) arg2a = c1  ; /* arg2a = dmin1(arg2a, c1) */
2058   alpha = asin(arg2a) ;
2059 /*
2060 c
2061 c     2. get plt and pln (still legalizing arguments)
2062 c
2063 */
2064   c5=stdlat*pi180 ;
2065   c6=hsign*stdlat*pi180 ;
2066   arg2a = cos(c5)*cos(bb) + sin(c6)*sin(c4) ;
2067   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = dmax1(arg2a,-c1) */
2068   if(  c1 < arg2a ) arg2a = c1  ; /* arg2a = dmin1(arg2a, c1) */
2069   plt1   = asin(arg2a) ;
2070
2071   arg2a = sin(bb)*cos(alpha)/cos(plt1) ;
2072
2073   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = dmax1(arg2a,-c1) */
2074   if(  c1 < arg2a ) arg2a =  c1 ; /* arg2a = dmin1(arg2a, c1) */
2075   pln1   = asin(arg2a) ;
2076
2077
2078 /*
2079 c
2080 c    test for passage of the 90 degree longitude (duallity in pln)
2081 c         get plt for which pln=90 when lti is the latitude
2082 c
2083 */
2084   arg2a = sin(c4)/sin(c6) ;
2085   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = dmax1(arg2a,-c1) */
2086   if(  c1 < arg2a ) arg2a =  c1 ; /* arg2a = dmin1(arg2a, c1) */
2087   plt90 = asin(arg2a) ;
2088
2089 /*
2090 c
2091 c         get help arc bb and angle alpha
2092 c
2093 */
2094   arg2a = cos(c5)*sin(plt90) ;
2095   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = dmax1(arg2a,-c1) */
2096   if(  c1 < arg2a ) arg2a =  c1 ; /* arg2a = dmin1(arg2a, c1) */
2097   bb    = acos(arg2a) ;
2098
2099   arg2a = sin(c4)/sin(bb) ;
2100   if( -c1 > arg2a ) arg2a = -c1 ; /* arg2a = dmax1(arg2a,-c1) */
2101   if(  c1 < arg2a ) arg2a =  c1 ; /* arg2a = dmin1(arg2a, c1) */
2102   alpha = asin(arg2a) ;
2103
2104 /*
2105 c
2106 c         get glolim - it is nesc. to test for the existence of solution
2107 c
2108 */
2109   argu2  = cos(c2)*cos(bb) / (1.-sin(c4)*sin(bb)*sin(alpha)) ;
2110   if( fabs(argu2) > c1 ) {
2111     glolim = 999.0;
2112   } else {
2113     glolim = acos(argu2)/pi180;
2114   }
2115
2116 /*
2117 c
2118 c     modify (if nesc.) the pln solution
2119 c
2120 */
2121   if( ( fabs(argu1) > glolim && lti <= stdlat ) || ( lti > stdlat ) ) {
2122     pln1 = pi180*180.0 - pln1;
2123   }
2124 /*
2125 c
2126 c     the solution is symmetric so the direction must be if'ed
2127 c
2128 */
2129   if(argu1 < 0.0) {
2130     pln1 = -pln1;
2131   }
2132 /*
2133 c
2134 c     convert the radians to degrees
2135 c
2136 */
2137   plt = plt1/pi180 ;
2138   pln = pln1/pi180 ;
2139
2140
2141 /*
2142 c
2143 c     to obtain a rotated value (ie so x-axis in pol.ste. points east)
2144 c     add 270 to longitude
2145 c
2146 */
2147   pln=fmod(pln+270.0,360.0) ;
2148
2149  l2000:
2150
2151 /*
2152 c
2153 c     this program convert polar stereographic coordinates to x,y ditto
2154 c     longitude:   0 - 360  ; positive to the east
2155 c     latitude : -90 -  90  ; positive for northern hemisphere
2156 c     it is assumed that the x-axis point towards the east and
2157 c     corresponds to longitude = 0
2158 c
2159 c     tsp 20/06-89
2160 c
2161 c     constants and functions
2162 c
2163 */
2164   facpla = radius*2.0/(1.0+sin(plt*pi180))*cos(plt*pi180);
2165   x = facpla*cos(pln*pi180) ;
2166   y = facpla*sin(pln*pi180)  ;
2167
2168   *grdi=(x-xref)/delx + xiref;
2169   *grdj=(y-yref)/dely + yjref;
2170
2171   return;
2172
2173 }
2174
2175
2176 #if USESDF == 1
2177 #ifdef STNDALN
2178
2179 #define Success 1
2180 #define Failure 0
2181
2182 /* initialize a netCDF standard file structure */
2183 int
2184 init_io_std (std_ptr)
2185 IO_STD    **std_ptr;            /* pointer to netCDF data structure */
2186 {
2187   int         init_dim_info ();
2188   void        free_io_std ();
2189
2190   if ((*std_ptr) != NULL)
2191     free_io_std (std_ptr);
2192
2193   if (((*std_ptr) = (IO_STD *) malloc (sizeof (IO_STD))) == NULL)
2194   {
2195         printf ("Could not allocate memory for netCDF/HDF-SDS structure.\n");
2196         return Failure;
2197   }
2198
2199   /* initialize contents of structure */
2200   (*std_ptr)->cdfid = -1;
2201   (*std_ptr)->ndims = 0;
2202   (*std_ptr)->nvars = 0;
2203   (*std_ptr)->ngatts = 0;
2204   (*std_ptr)->recdim = -1;
2205   (*std_ptr)->time_type = CDC;
2206
2207   (*std_ptr)->first_gattr = NULL;
2208
2209   /* don't create variable list quite yet */
2210   (*std_ptr)->var = NULL;
2211
2212   /* intialize dimension information */
2213   if (init_dim_info ((*std_ptr)->dimids, (*std_ptr)->dimnam,
2214                      (*std_ptr)->dimsiz) != Success)
2215     return Failure;
2216
2217   return Success;
2218 }
2219
2220 /* initialize dimension information */
2221 int
2222 init_dim_info (dimids, dimnam, dimsiz)
2223 int        *dimids;             /* array of dimension IDs   */
2224 char        dimnam[MAX_NC_DIMS][MAX_NC_NAME + 1];       /* array of dimension
2225                                                          * names */
2226 long       *dimsiz;             /* array of dimension sizes */
2227 {
2228   int         i;
2229
2230   /* set all dimension information to bogus values */
2231   for (i = 0; i < MAX_NC_DIMS; i++)
2232   {
2233     dimids[i] = -1;
2234     dimnam[i][0] = '\0';
2235     dimsiz[i] = -1;
2236   }
2237
2238   return Success;
2239 }
2240
2241 /* free a netCDF standard file structure */
2242 void
2243 free_io_std (std_ptr)
2244 IO_STD    **std_ptr;
2245 {
2246   void        free_var_info ();
2247   int         free_netcdf_att_list ();
2248
2249   if (*std_ptr != NULL)
2250   {
2251     /* if the variable list exists, free it */
2252     if ((*std_ptr)->var != NULL)
2253       free_var_info (&((*std_ptr)->var));
2254
2255     /* free the global attributes if they have been allocated */
2256     if ((*std_ptr)->first_gattr != NULL)
2257       free_netcdf_att_list (&((*std_ptr)->first_gattr));
2258
2259     /* now free the IO_STD structure itself */
2260     free (*std_ptr);
2261     *std_ptr = NULL;
2262   }
2263
2264   return;
2265 }
2266
2267 /* free a variable structure */
2268 void
2269 free_var_info (var)
2270 VAR_INFO  **var;
2271 {
2272   void        free_var_info ();
2273   int         free_netcdf_att_list ();
2274
2275   /* go through list to the end and free all variable structures */
2276   if ((*var)->next != NULL)
2277     free_var_info (&((*var)->next));
2278
2279   if ((*var)->first_vattr != NULL)
2280     free_netcdf_att_list (&((*var)->first_vattr));
2281
2282   /* if data space has been allocated, free it */
2283   if ((*var)->data != NULL)
2284     free ((*var)->data);
2285
2286   /* now free the variable structure itself */
2287   free (*var);
2288   *var = NULL;
2289
2290   return;
2291 }
2292
2293 /* Free a netCDF attribute list. */
2294 int
2295 free_netcdf_att_list (first_attr)
2296 struct attrib_list **first_attr;        /* First attribute in list. */
2297 {
2298   struct attrib_list *temp_attr,
2299              *save_attr;
2300
2301   temp_attr = *first_attr;
2302   while (temp_attr != NULL)
2303   {
2304     save_attr = temp_attr->next;
2305     if (temp_attr->data != NULL)
2306       free (temp_attr->data);
2307     free (temp_attr);
2308     temp_attr = save_attr;
2309   }
2310   *first_attr = NULL;
2311   return Success;
2312 }
2313
2314 #endif
2315 #endif
Note: See TracBrowser for help on using the browser.