/* * Copyright(c) 2003, Space Science and Engineering Center, UW-Madison * Refer to "McIDAS Software Acquisition and Distribution Policies" * in the file mcidas/data/license.txt */ /**** $Id: gribfunc.c,v 1.69 2011/11/03 17:04:25 scottl Rel $ *** */ #include #include #include #include #include #include #include #include #include #include "mcidas.h" #include "mcncdf.h" #include "mcgrib.h" /* also includes servutil.h */ extern int M0TestGridHeader(int *, GridRequestObj *); #include "mcgrib2.h" #include "servutil.h" #define HEDSIZ (64) static int GRIBSaveGridData; int M0MatchGribNumberRequest(char *, GridRequestObj *); int M0MakeInt(unsigned char *, int); int M0GribFileType(char *); int M0IsInArray(int , int * , int ); int * M0InsertInIArray(int , int * , int ); char ** M0InsertInCArray(int , char ** , char * ); int M0AddInfoToGridRequest(const char * , GridRequestObj * ); int M0IsStitchable(int ); int M0IsECMFStitchable(int, int); int M0FindGribRange(int , int , int *, int *); int GetGRIBData( GribGrid_Header *, Fint **, Fint ** ); int M0IsPartialGrib(Fint * , int , GridRequestObj * , int * , int * , int * ); int M0RemoveDayTimeFhour( FILELIST **, GridRequestObj *); int M0CountGridHeaderN0SubSect(GribGrid_Header **, int *, GridDerive *, int *, int , GridRequestObj *, int, int *); int M0CountGridHeader ( GribGrid_Header **, int *, GridDerive *, int *, int, GridRequestObj * , int , int * , double, double, double, double, int , int , int , int, int ); int M0GribGetGridHeader ( GribGrid_Header *, Fint * ); int M0GribGetGridData ( GribGrid_Header ** , int *, Fint *, Fint * ); int M0GribMkMcFileHeader(int **, char * ); /*int M0TestGridHeader(int *, GridRequestObj *);*/ int M0GribGridCompare ( int , int *, int ) ; int M0ReorderList ( GribGrid_Header ** , GridRequestObj *, int ) ; int M0MakeStructIndex(GribGrid_Header * , GridRequestObj *, int, int , GribGrid_Header *** , int ** ); int M0MatchListuv ( GribGrid_Header **, Fint * ) ; int M0CompareGridHead(int * ,int *, int ) ; int M0CompareGridHeaduv(int * ,int *, int ) ; int M0GribGetGridvData( GribGrid_Header ** , int *, Fint * , Fint * , Fint * ); int M0GribGetGridvHeader( GribGrid_Header ** , Fint * , Fint * ); int M0GribReadGridData( GribGrid_Header * , Fint * , Fint * ); int IsNodeComplete(GridDerive *, GribGrid_Header *); int CheckMatchDeriveNode(GridDerive *, GribGrid_Header *, GribGrid_Header *); /*int M0GribMakeGridHeader(unsigned char * , int , Fint *);*/ int M0GribCheckSpecialCase(char * , int ); int M0PrintSizes( GribGrid_Header *); int M0NodeComplete(GribGrid_Header * ); int M0DiffGeoGrib(GribGrid_Header * , GribGrid_Header * ); int M0CompareGribGrid_Derive(GribGrid_Header *, GridDerive *); int M0FindDeriveMatchGridHeader(GribGrid_Header **, int * , int, GridDerive * , int **, int * ); int M0MatchNextDerive (GribGrid_Header ** , GridDerive * , Fint * , int *); int M0GetFirstDerive(GribGrid_Header ** , int *, int *, GridDerive * , Fint ** , Fint ** ); int M0GetMatchDerive(GridDerive *, GribGrid_Header ** , int *, Fint * , Fint ** , Fint ** ); int M0FreeGribGrid( GribGrid_Header *, GribGrid_Header *); int McIntLon(float ); /*int M0Grib2McData(GribGrid_Header * , Fint **, Fint **);*/ /*int M0GetProductInfoTemplate00(long * , long , char ** , int * , char ** , int * , double * , double * , int * , int * , int * );*/ int M0GetProductInfoTemplate(g2int, g2int * , g2int , g2int, char ** , int * , char ** , int * , double * , double * , int*, int*,int * , int * , int *, int * ,int *, int *); /*int M0GetNavFromGribTemplate(int , long * , Fint ** , int *);*/ int IsGribRequested(GridRequestObj * , int, int); /*int M0GetMeanMaxMinScale(float * , Fint * , double * , double * , double * , int *); * */ /*int M0IsGoodPosNum(int , int , int );*/ static double actual_data[2*GB_MAX_DATA_PTS]; char gribdbg[512]; /* *$ Name: *$ M0GribGetGridData -- get grid data from a GRIB file *$ *$ Interface: *$ int M0GribGetGridData( GribGrid_Header ** AddressIndex, *$ int * LastInStitch, Fint * McGridData, Fint * McGridHeader) *$ *$ Input: *$ AddressIndex - array of structure addresses *$ LastInStitch - Is this the last of a series of stitchable grids? *$ *$ Input and Output: *$ none *$ *$ Output: *$ McGridData - scaled integer gridded arrary *$ McGridHeader - 64-word grid header *$ *$ Return values: *$ 0 - success *$ -5 - Failed to open GRIB file *$ -6 - fseek failure on file *$ -7 - malloc error *$ -10 - mcgrb2mc failure -- did not convert from GRIB to McGrid *$ -15 - retrieved grid header different from stored gridheader *$ *$ Remarks: *$ Open the GRIB file indicated in the GribGrid_Header structure, *$ and read in the number of bytes of data starting at the offset, *$ also both indicated in the structure. Then convert the GRIB *$ data to a McIDAS grid and return the grid and grid header *$ If this is a derived grid, retrieve all the grids and paste *$ them together. *$ LastInStitch is 1 if this is the last of a series of grids to *$ stitch together (or the only grid) *$ *$ Categories: *$ grid */ int M0GribGetGridData( GribGrid_Header ** AddressIndex, int * LastInStitch, Fint * McGridDat, Fint * McGridHdr) { Fint McHeader1[HEDSIZ]; /* 64-words grid header */ Fint McHeader2[HEDSIZ]; /* 64-words grid header */ Fint * McGridData = NULL; /* scaled integer gridded data */ GribGrid_Header * ThisGribGrid; int missing; /* missing value for grid (z80808080) */ int i,j; /* loop bound */ int iret; /* loop control */ int gridsize; /* um..size of the grid described in gridheader */ int FirstStitch,LastStitch; /* grib geo numbers for stitchable grids */ /* int AllFound;*/ FirstStitch = 255; LastStitch = 0; i = 0; missing = 0x80808080; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (ThisGribGrid == NULL) return(-7); memcpy( (void *)ThisGribGrid, (void *)AddressIndex[i], sizeof(GribGrid_Header)); memcpy((void *) &McHeader1[0],(void *) &ThisGribGrid->MCGRIDHEADER[0],sizeof(int)*HEDSIZ); gridsize = McHeader1[0]; McGridData = (Fint *)malloc(gridsize*sizeof(Fint));/*Grid uses 4-byte words */ if (McGridData == (Fint *)NULL) { (void)sprintf(gribdbg,"Failed to malloc space for McIDAS grid of size %d", gridsize); M0sxtrce(gribdbg); return(-7); } (void)sprintf(gribdbg,"Last structure is %d %d ",i,LastInStitch[i]); M0sxtrce(gribdbg); /* get the data in the grid .... this could be either ** the only data that is retrieved, or it could be ** the first of up to 8 octants retrieved */ iret = M0GribReadGridData(ThisGribGrid,McGridData,McHeader1); if (iret < 0) { memcpy( (void *)McGridHdr, (void *)&McHeader1[0],256); free(McGridData); return(iret); } /* Get any grids that will be stitched together */ while (LastInStitch[i] != 1) { int countgrids = 1; Fint * McGridData2 = NULL; if (ThisGribGrid->MCGRIDHEADER[48] > LastStitch) LastStitch = ThisGribGrid->MCGRIDHEADER[48]; if (ThisGribGrid->MCGRIDHEADER[48] < FirstStitch) FirstStitch = ThisGribGrid->MCGRIDHEADER[48]; (void)sprintf(gribdbg,"I is %d %d, Firststitch %d last %d ", i,LastInStitch[i],FirstStitch,LastStitch); M0sxtrce(gribdbg); i++; memcpy( (void *)ThisGribGrid, (void *)AddressIndex[i], sizeof(GribGrid_Header)); if (ThisGribGrid->MCGRIDHEADER[48] > LastStitch) LastStitch = ThisGribGrid->MCGRIDHEADER[48]; if (ThisGribGrid->MCGRIDHEADER[48] < FirstStitch) FirstStitch = ThisGribGrid->MCGRIDHEADER[48]; (void)sprintf(gribdbg,"I is %d %d, Firststitch %d last %d %d ", i,LastInStitch[i],FirstStitch,LastStitch,McHeader1[0]); M0sxtrce(gribdbg); McGridData2 = (Fint *)malloc(sizeof(Fint)*McHeader1[0]); if (McGridData2 == NULL) return(-7); /* Grab all the grib data and paste them together */ iret = M0GribReadGridData(ThisGribGrid,McGridData2,McHeader2); countgrids++; (void)sprintf(gribdbg,"GribReadGridData returns %d %x %d ",iret,McGridData,countgrids); M0sxtrce(gribdbg); for (j = 0; j < McHeader2[0]; j++) { if (McGridData2[j] != missing) { McGridData[j] = McGridData2[j]; } } free(McGridData2); } if (FirstStitch < LastStitch) { if (FirstStitch > 12) { if (FirstStitch >= 21 && FirstStitch <= 24) McHeader1[48] = 2124; if (FirstStitch >= 61 && FirstStitch <= 64) McHeader1[48] = 6164; if (FirstStitch == 25 || FirstStitch == 26) McHeader1[48] = 2526; if (FirstStitch >= 37 && FirstStitch <= 44) McHeader1[48] = 3744; } else { if (FirstStitch > 4 && FirstStitch < 9) { McHeader1[48] = 5678; } else { McHeader1[48] = 14912; /* special ECMWF case */ } } } (void)sprintf(gribdbg,"Save the data?? %d ",GRIBSaveGridData); M0sxtrce(gribdbg); if (GRIBSaveGridData == 1) { M0sxtrce("Save the data!!!!!"); memcpy( (void *)McGridDat, (void *)McGridData,sizeof(int)*McHeader1[0]); } memcpy( (void *)McGridHdr, (void *)&McHeader1[0],(size_t)256); free(McGridData); return(0); } /* *$ Name: *$ M0RemoveDayTimeFhour -- remove unneeded files from a list *$ *$ Interface: *$ int M0RemoveDayTimeFhour( FILELIST **satisfy, GridRequestObj **Request) *$ *$ Input: *$ Request - GridRequestObj that matches sort conditions *$ *$ Input and Output: *$ satisy - FILELIST structure containing GRIB files from dataset *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - success *$ -1 - file does not contain GRIB data *$ -10 - malloc error *$ *$ Remarks: *$ M0RemoveDayTimeFhour removes those grib files in the list in *$ FILELIST satisfy that do not match the days/times/fhours in *$ the GridRequestObj Request which contains the sort conditions *$ *$ Categories: *$ grid */ int M0RemoveDayTimeFhour( FILELIST **satisfy, GridRequestObj *Request) { int firstfound; /* first valid node found */ int i; /* loop control */ int ntimes; /* # of times in the SORT clauses */ int ndays; /* # of days in the SORT clauses */ int nfhours; /* # of fhours in the SORT clauses */ int YES=1; int NO=0; int match; char daycheck[10]; /* string like .2003170.(day is yyyyddd)*/ char timecheck[7]; /* string of form .1200. (time is HMS) */ char fhourcheck[6]; /* string of form .12. (fhour is int) */ char filename[256]; /* filename containing GRIB data */ FILELIST *Tsatisfy = NULL; FILELIST *LastLink = NULL; FILELIST *FirstLink = NULL; ntimes = Request->n_time; ndays = Request->n_day; nfhours = Request->n_vtime; firstfound = 0; if (ntimes == 0 && ndays == 0 && nfhours == 0) { /* return -- there is nothing to do! */ return(0); } Tsatisfy = (FILELIST *)malloc(sizeof(FILELIST)); FirstLink = (FILELIST *)malloc(sizeof(FILELIST)); LastLink = (FILELIST *)malloc(sizeof(FILELIST)); if (FirstLink == NULL || LastLink == NULL || Tsatisfy == NULL) { M0sxtrce("Could not make FILELISTs "); return(0); } memcpy(Tsatisfy,*satisfy,sizeof(FILELIST)); LastLink = NULL; while (Tsatisfy != NULL) { (void)strcpy(filename,Tsatisfy->name); M0sxtrce(filename); /* if any of the times match, keep the node */ match = NO; for (i = 0; i < ntimes ; i++) { int itime; itime = Request->time[i]; if (itime < 10) { (void)sprintf(timecheck,".%1d.",itime); } else { if (itime < 100) { (void)sprintf(timecheck,".%2d.",itime); } else { if (itime < 1000) { (void)sprintf(timecheck,".%3d.",itime); } else { if (itime < 10000) { (void)sprintf(timecheck,".%4d.",itime); } else { if (itime < 100000) { (void)sprintf(timecheck,".%4d.",itime/10); } else { (void)sprintf(timecheck,".%4d.",itime/100); } } } } } if (strstr(filename,timecheck) != NULL) match=YES; } if (ntimes > 0 && match == NO) { /* remove node */ M0sxtrce("Remove Node"); if (LastLink != NULL) { LastLink->next = Tsatisfy->next; } /* note that we do not want to change the LastLink... ** just the one we'll be working on next **/ match = NO; goto ENDOFWHILE; } /* if any of the days match, keep the node */ match = NO; for (i = 0; i < ndays ; i++) { int yearday; yearday = Request->day[i]; if (Mccydok(yearday) < 0) { /* year in unexpected format, try to recover */ int ccyyddd; if (Mciydtocyd(yearday,&ccyyddd) < 0) { /* error out */ goto ENDOFLOOP; } yearday = ccyyddd; } (void)sprintf(daycheck,".%7d.",yearday); if (strstr(filename,daycheck) != NULL) match=YES; ENDOFLOOP: ; } if (ndays > 0 && match == NO) { /* remove node */ M0sxtrce("remove a node"); if (LastLink != NULL) { LastLink->next = Tsatisfy->next; } /* note that we do not want to change the LastLink... ** just the one we'll be working on next **/ match=NO; goto ENDOFWHILE; } /* if any of the vtimes/fhours match, keep the node */ match = NO; for (i = 0; i < nfhours ; i++) { int fhour; fhour = Request->vtime[i]; if (fhour < 10) { (void)sprintf(fhourcheck,".%1d.",fhour); } else { if (fhour < 100) { (void)sprintf(fhourcheck,".%2d.",fhour); } else { (void)sprintf(fhourcheck,".%3d.",fhour); } } if (strstr(filename,fhourcheck) != NULL) match=YES; } if (nfhours > 0 && match == NO) { /* remove node */ if (LastLink != NULL) { LastLink->next = Tsatisfy->next; } /* note that we do not want to change the LastLink... ** just the one we'll be working on next **/ match=NO; goto ENDOFWHILE; } /* if the code is here, then a node has not been removed, and ** the first node can be specified, if it hasn't happened ** already **/ (void)sprintf(gribdbg,"Assign node to %x %x %x %x ",FirstLink,*FirstLink, Tsatisfy,*Tsatisfy); M0sxtrce(gribdbg); if (firstfound == 0) { FirstLink = Tsatisfy; M0sxtrce("First link"); /*memcpy(FirstLink,Tsatisfy,sizeof(FILELIST));*/ firstfound = 1; } LastLink = Tsatisfy; /* memcpy(LastLink,Tsatisfy,sizeof(FILELIST));*/ ENDOFWHILE: Tsatisfy = Tsatisfy->next; } Mctrace(1,"GribGrid","All Done in Remove daytime fhour"); *satisfy = FirstLink; return(0); } /* *$ Name: *$ M0GribMakeGridHeader -- make the grid header from the *$ GRIB data in the buffer *$ *$ Interface: *$ int M0GribMakeGridHeader( char *buffer, int bufsize, *$ int * Header) *$ *$ Input: *$ buffer - buffer containing GRIB data *$ bufize - size of buffer *$ *$ Input and Output: *$ none *$ *$ Output: *$ GHead - McIDAS grid header of data *$ *$ Return values: *$ 0 - success *$ -1 - file does not contain GRIB data *$ -2 - malloc failure *$ -10 - file software errors (fopen or fstat) *$ <-1000 - Mcgribdecoder error *$ <-2000 - Mcmkmcgrid error *$ *$ Remarks: *$ Decode the header information in each of the GRIB Files *$ to see if they match the search conditions. Return a linked *$ list of grid headers with the GRIB file and byte offset *$ where they can be found. *$ *$ Categories: *$ grid */ int M0GribMakeGridHeader(unsigned char * buffer, int bufsize, Fint * GHead) { static IS is= { 0 }; static PDS pds= { 0 }; static GDS gds= { 0 }; static BMS bms= { 0 }; static BDS bds= { 0 }; GBTAB000 gbtab000; GBTAB002 gbtab002; GBTAB004 gbtab004; GBTAB00A gbtab00a; GBTAB00B gbtab00b; MCGRIDHEADER mcheader; int size; int ok; /* int i;*/ char * no_dec_file = {"" }; unsigned char * NewBuf = NULL; size = bufsize; NewBuf = (unsigned char *)malloc(sizeof(unsigned char)*size); if (NewBuf == NULL) return(-2); memcpy(NewBuf,buffer,size); ok = Mcgribdecoder( (void *)NewBuf, size, &is, &pds, &gds, &bms, &bds, &actual_data[0], &gbtab000, &gbtab002, &gbtab004, &gbtab00a, &gbtab00b, no_dec_file); if (ok < 0) { (void)sprintf(gribdbg, "M0GribMakeGridHeader ERROR: Failed to decode grib file, ok = %d",ok); M0sxtrce(gribdbg); return(-1000+ok); } /* actual data is NULL, and the data to be read in is NULL -- don't ** need to know....note that at this point, Mcmkmcgrid will fill in ** a 0 for the scaling, since the data values aren't known ****/ ok = Mcmkmcgrid(&pds,&gds,&bms,&actual_data[0], &gbtab002,&gbtab004,&gbtab00a,&gbtab00b,&mcheader,NULL); if (ok < 0) { (void)sprintf(gribdbg, "M0GribMakeGridHeader ERROR: Failed to make grid, ok = %d",ok); M0sxtrce(gribdbg); return(-2000+ok); } (void)sprintf(gribdbg,"Read in file from day %d time %d fhour %d parameter %d ", mcheader.j_date,mcheader.run_time,mcheader.valid_time, mcheader.parameter); M0sxtrce(gribdbg); memcpy((void *)&GHead[0],&mcheader,(size_t)256); free(NewBuf); return(0); } /* *$ Name: *$ M0CountGridHeaderNOSubSect -- count bytes with grids/grid headers *$ *$ Interface: *$ int M0CountGridHeaderNOSubSect( GribGrid_Header ** StructIndex, *$ int * Last, *$ GridDerive *GD, int * largest, int ngrids_to_send , *$ GridRequestObj * Grids_R, int doGridDerive) *$ *$ Input: *$ StructIndex - array of structure addresses *$ Last - is structure that last in a series of stitchables? *$ GD - Grid derive Object *$ GR - Grid Request Object showing sort conditions *$ ngrids_to_send - number of grids to send to client *$ doGridDerive - flag saying deriving is being done *$ *$ Input and Output: *$ none *$ *$ Output: *$ largest - largest number of points in grid in linked list *$ *$ Return values: *$ >0 - number of grid headers in linked list *$ 0 - structure contains no data *$ -10 - trapped an infinite loop? *$ -20 - Out of memory *$ *$ Remarks: *$ Go through the GribGrid_Header structure and count the *$ number of gridheaders. *$ Note that some of the elements on the stack will be later *$ combined; only count one of the headers in each of these. *$ The gridheaders already reflect the stitched-together size *$ of the grid. *$ In addition, if a Derivation is being done, match up the grids *$ *$ Categories: *$ grid */ int M0CountGridHeaderNOSubSect( GribGrid_Header ** StructAddress, int *Last, GridDerive *GD, int *Largest, int ngrids_to_send, GridRequestObj * GR, int doGridDerive, int * bytes) { int ngrids=0; int TotBytes=0; int test = 0; int cnt = 0; int i; int Index; int ok,iret; int * GridHeader; int uGridHeader[HEDSIZ]; int TotDerive; /* number of grids needed to derive*/ GribGrid_Header * ThisGribGrid; GridDerive * ThisGD = NULL; GridDerive * CntGD = NULL; i = 0; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); GridHeader = (int *)malloc(sizeof(int)*HEDSIZ); ThisGD = (GridDerive *)malloc(sizeof(GridDerive)); CntGD = (GridDerive *)malloc(sizeof(GridDerive)); if ( GridHeader == NULL || ThisGribGrid == NULL || ThisGD == NULL || CntGD == NULL ) return(-20); /* simplest case -- no Deriving, no uvflag */ if (doGridDerive == 0 && GR->uvflag == 0 ) { int table2resetflag=1; (void)sprintf(gribdbg,"Simple case, StructAddy %p ",StructAddress[i]); M0sxtrce(gribdbg); iret = gbtable002( (IS *)NULL,(PDS *)NULL,(GBTAB002 *)NULL,table2resetflag); while ( StructAddress[i] != (GribGrid_Header *) NULL ) { memcpy( (void *)ThisGribGrid,(void *)StructAddress[i], sizeof(GribGrid_Header)); if (ThisGribGrid->MCGRIDHEADER[0] > test) test = ThisGribGrid->MCGRIDHEADER[0]; if (Last[i] == 1) { ngrids++; TotBytes += 4*ThisGribGrid->MCGRIDHEADER[0]; } i++; cnt++; if (cnt > 1000000) { (void)sprintf(gribdbg,"Infinite loop?"); M0sxtrce(gribdbg); return(-10); } if (ngrids >= ngrids_to_send) goto EndCount; } goto EndCount; } if (GR->uvflag == 1) { /* need paired u-v grids...go through and find 'em */ i = 0; (void)sprintf(gribdbg,"Paired parameters, %d Address: %p",i,StructAddress[i]); M0sxtrce(gribdbg); while (StructAddress[i] != (GribGrid_Header *)NULL) { char tstr[5]; int tint; (void)sprintf(gribdbg, "Paired parameters, %d Address: %p %d",i,StructAddress[i],Last[i]); M0sxtrce(gribdbg); if (Last[i] == 1) { /* only compute sizes for ** the last in a series of ** grids that will be sent back ** after being combined */ memcpy( (void *)ThisGribGrid,(void *)StructAddress[i], sizeof(GribGrid_Header)); tint = ThisGribGrid->MCGRIDHEADER[6]; memcpy(&tstr[0],&tint,sizeof(int)); tstr[4] = 0; (void)sprintf(gribdbg,"size %d lev %d par >%s< ",ThisGribGrid->MCGRIDHEADER[0],ThisGribGrid->MCGRIDHEADER[9],tstr); M0sxtrce(gribdbg); if ( strcmp(tstr,"U ") == 0 || strcmp(tstr,"U") == 0 || strcmp(tstr," U") == 0) { (void)sprintf(gribdbg,"Found u --find v match %p",StructAddress[i]); M0sxtrce(gribdbg); iret = M0GribGetGridHeader(ThisGribGrid,&uGridHeader[0]); iret = M0MatchListuv(StructAddress,uGridHeader); if (iret == 1) { M0sxtrce("Found a matching v grid!"); ngrids += 2; TotBytes += 2*4*uGridHeader[0]; if (uGridHeader[0] > test) test = uGridHeader[0]; } } } cnt++; i++; if (cnt > 1000000) { (void)sprintf(gribdbg,"Infinite loop?"); M0sxtrce(gribdbg); return(-10); } if (ngrids >= ngrids_to_send) goto EndCount; } goto EndCount; } /* the next code segment only executes if derivation is done on the client */ /* in other words -- the PARSE= string has been passed to the server */ M0sxtrce("Derived grids!"); memcpy( (void *)ThisGD, (void *)GD, sizeof(GridDerive)); memcpy( (void *)CntGD, (void *)GD, sizeof(GridDerive)); /* count the number of grids in GridDerive structure */ TotDerive = 0; while (CntGD != NULL) { if (CntGD->present != 0) TotDerive++; CntGD = CntGD->nextDerive; } (void)sprintf(gribdbg,"TotDerive is %d, ngrids_to_send %d %p ", TotDerive,ngrids_to_send,StructAddress[0]); M0sxtrce(gribdbg); ngrids = 0; i = 0; while (StructAddress[i] != (GribGrid_Header *)NULL) { memcpy( (void *)ThisGD, (void *)GD, sizeof(GridDerive)); (void)sprintf(gribdbg,"Call FindDeriveMatchGridHeader >%s< >%s< \n ", ThisGD->parm,GD->parm); M0sxtrce(gribdbg); ok = M0FindDeriveMatchGridHeader(StructAddress,Last,i,ThisGD,&GridHeader,&Index); (void)sprintf(gribdbg,"FindDeriveMatchGridDerive returns %d ",ok); M0sxtrce(gribdbg); if (ok == 0) { /* found the grid -- and all the matching grids needed ** to derive a grid */ ngrids += TotDerive; TotBytes += TotDerive*4*GridHeader[0]; if (GridHeader[0] > test) test = GridHeader[0]; (void)sprintf(gribdbg,"ngrids found so far: %d ",ngrids); M0sxtrce(gribdbg); if (ngrids >= ngrids_to_send) goto EndCount; i = Index; } i++; } free(ThisGribGrid); EndCount: ; (void)sprintf(gribdbg,"Cnt is %d ngrids is %d ",cnt,ngrids); M0sxtrce(gribdbg); *Largest = test; *bytes = TotBytes; /*nfiles = 1;*/ return(ngrids); } /* *$ Name: *$ M0GribMkMcFileHeader - Make a McIDAS gridfile header *$ *$ Interface: *$ #include "mcidas.h" *$ *$ int *$ M0GribMkMcFileHeader(int *McFileHeader, char * filename) *$ *$ Input: *$ filename - file containing GRIB data *$ *$ Input and Output: *$ none *$ *$ Output: *$ McFileHeader - McIDAS GRID format File header *$ *$ Return values: *$ 0 - success *$ *$ Remarks: *$ Create a McIDAS Gridfile header *$ *$ Categories: *$ grid */ int M0GribMkMcFileHeader(int ** McFileHeader, char * filename) { int stringlen; int thisday; int thistime; int ok; int * TFileHeader = NULL; /* char head[11]=" GRIB file";*/ char * EndFile; char * headertitle = NULL; headertitle = (char *)malloc(sizeof(char)*33); TFileHeader = (int *)malloc(sizeof(int)*HEDSIZ); EndFile = malloc(sizeof(char)*512); if (headertitle == NULL || TFileHeader == NULL || EndFile == NULL) return(-1); memset(headertitle,0,(size_t)33); EndFile = strrchr((const char *)filename,(int) '/'); if (strrchr(filename,'/') == NULL) { (void)sprintf(EndFile,"%s",filename); } (void)sprintf(gribdbg,"EndFile : >%s< %d ",EndFile,strlen(EndFile)); M0sxtrce(gribdbg); /* There are 32 slots available in headertitle....head takes up 11, and *** there are 4 others after that (the ellipses)...so put a termination ** in Endfile at the 1:th character */ stringlen = strlen(EndFile); (void)sprintf(gribdbg,"String >%s< has length %d \n",EndFile,stringlen); M0sxtrce(gribdbg); EndFile[32] = (char)0; strtofs( (char *)&headertitle[0],(char *)&EndFile[0], 32); M0sxtrce(headertitle); strtofs((void *)TFileHeader,(void *)headertitle,sizeof(char)*32); if (stringlen < 32) { for (ok = stringlen; ok < 32; ok++) { TFileHeader[ok] = (char)32; } } ok = Mcgetdaytime(&thisday,&thistime); (void)sprintf(gribdbg,"Returned %d %d %d %x",ok,thisday,thistime,*McFileHeader); M0sxtrce(gribdbg); TFileHeader[8] = thistime; TFileHeader[9] = thisday; TFileHeader[10] = 99999; TFileHeader[14] = 1; memcpy( (void *)*McFileHeader, (void *)&TFileHeader[0], (size_t)256); /* free(EndFile); */ M0sxtrce("return"); return (0); } /* *$ Name: *$ M0GribGetGridHeader -- return grid header out of structure *$ *$ Interface: *$ int M0GribGetGridHeader(GribGrid_Header *Valid, *$ Fint * GHeader) *$ *$ Input: *$ Valid - linked list including grid headers *$ *$ Input and Output: *$ none *$ *$ Output: *$ GHeader - McIDAS grid header *$ *$ Return values: *$ 0 - success *$ *$ Remarks: *$ Get the McIDAS grid header from the GribGrid_Header structure *$ *$ Categories: *$ grid */ int M0GribGetGridHeader ( GribGrid_Header *Valid, Fint * GHead) { /* int i,j; */ /* Loop bounds */ /* int AllFound; */ /* have all the grid structures been found? */ int Head[HEDSIZ]; /* int numberDerivedFound=0; *//* number of derived grids found */ /* int numConstituents; */ /* number of grids expected */ /* int numHdrVals;*/ /* number of different header values */ /* GribGrid_Header * Top;*/ /* int MissFlag;*/ /* bit flag for missing consituents */ /* int Miss0;*/ char slot[49]; /* int * Slots = NULL; int * SlotVals = NULL; int * MissSlots = NULL; */ int i; for ( i = 0; i < HEDSIZ ; i++) { Head[i] = (int) Valid->MCGRIDHEADER[i]; } memcpy((void *)&slot[0],(void *)&Head[52],(size_t)48); slot[48] = (char)0; memcpy(GHead,&Head[0],HEDSIZ*sizeof(int)); return(0); } /* *$ Name: *$ M0TestGridHeader -- See if Grid Header matches request structure *$ *$ Interface: *$ int TestGridHeader(int *GridHeader, GridRequestObj * Request) *$ *$ Input: *$ GridHeader - 64-word McIDAS grid header *$ Request - server request structure against which to test *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - GridHeader does not match the Request structure *$ 1 - GridHeader matches the Request structure *$ *$ Remarks: *$ Compare the Grid header to the server request to see if *$ there is a match. *$ *$ Categories: *$ grid */ int M0TestGridHeader(int *GridHeader, GridRequestObj *GridRequest) { int i,ii,j; int thisfday; /* forecast day of grid */ int thisftime; /* forecast time of grid */ int match; /* did Grid Match any of Request parameters? */ double GridValue; int rc; /* int day,time,fhour;*/ char LevelUnit[5]; char LevelStr[5]; union { int idata; char cdata[5]; } GridString; /* go through the different structure parts to find what's ** matching and/or not matching the grid ** the GridRequestObj includes the following... typedef struct GridRequestObj int grid_begin; (start grid number) int grid_end; (end grid number) int f_day; (model forecast (valid) day, yyyyddd format) int f_time; (model forecast (valid) time, hhmmss format) int n_vtime; (number of forecast hours (intervals), hhmmss format) int *vtime; (array of the above) int n_time; (number of start times, hhmmss format) int *time; (array of the above) int n_day; (number of start days, yyyyddd format) int *day; (array of the above) int n_ens; (number of ensemble requests, integer format) char **ens; (array of ensemble requests) int n_level; (number of levels) double *d_level; (array of double type) char **c_level; (array of char type) char **u_level; (array of char type (units)) char *v_type; (vertical coordinate type) int n_parm; (number of paramters) char **parm; (array of parameters) char **u_parm; (array of units) int n_derv; (number of derive paramters) char **derv; (array of derive paramters) int n_src; (number of models) char **source; (source of data [ETA,UKMT,GFS....]) int n_proj; char **proj; union { (integer number of grids requested, or int ivalue; character constant 'ALL' for all grids) char *cvalue; (meeting selection criteria) } n_grids; int n_gribgeo; (number of grib geographic numbers) int *gribgeo; (GRIB number(s) of geographic location) int n_gribpar; (number of grib parameter numbers) int *gribpar; (GRIB number(s) for parameter) int n_gribmdl; (number of grib model numbers) int *gribmdl; (GRIB number(s) for model) int n_griblvl; (number of grib level numbers) int *griblvl; (GRIB number(s) for level) */ /* the day is stored in iyyddd format -- 103325 for day 325 in year 2003...the GridRequest structure is formatted 2003325 */ if (GridRequest->n_day > 0) { int iyyddd_day; int ccyyddd_day; int iret; iyyddd_day = GridHeader[3]; ccyyddd_day = iyyddd_day; if (Mccydok(iyyddd_day) < 0) iret = Mciydtocyd(iyyddd_day,&ccyyddd_day); if (M0GribGridCompare /* check the day */ (GridRequest->n_day,GridRequest->day,ccyyddd_day) == 0) { M0sxtrce("Day did not match"); return(0); } } if (M0GribGridCompare /* check the time */ (GridRequest->n_time,GridRequest->time,GridHeader[4]) == 0) { M0sxtrce("time did not match"); return(0); } if (M0GribGridCompare /* check the fhour */ (GridRequest->n_vtime,GridRequest->vtime,GridHeader[5]) == 0) { (void)sprintf(gribdbg,"vtime did not match %d %d \n",GridHeader[5], GridRequest->vtime[0]); M0sxtrce(gribdbg); return(0); } (void)sprintf(gribdbg,"gribgeo check: GridHeader 48: %d %d",GridHeader[48],GridRequest->n_gribgeo); M0sxtrce(gribdbg); for (i=0;in_gribgeo;i++) { (void)sprintf(gribdbg," Value # %d is %d %d",i,GridRequest->gribgeo[i],GridHeader[48]); M0sxtrce(gribdbg); } if (M0GribGridCompare /* check the grib geo #s */ (GridRequest->n_gribgeo,GridRequest->gribgeo,GridHeader[48]) == 0) { M0sxtrce("GRIB geo did not match"); return(0); } if (M0GribGridCompare /* check the grib par #s */ (GridRequest->n_gribpar,GridRequest->gribpar,GridHeader[49]) == 0) { M0sxtrce("GRIB parameter did not match"); return(0); } if (M0GribGridCompare /* check the grib model #s */ (GridRequest->n_gribmdl,GridRequest->gribmdl,GridHeader[50]) == 0) { M0sxtrce("GRIB model did not match"); return(0); } if (M0GribGridCompare /* check the grib level #s */ (GridRequest->n_griblvl,GridRequest->griblvl,GridHeader[51]) == 0) { M0sxtrce("GRIB level did not match"); return(0); } /* check to see if forecast day/forecast time match if they are ** specified in the GridRequestObject **/ if (GridRequest->f_day != -1) { rc = GetForecastDayTime (GridHeader[3],GridHeader[4],GridHeader[5],&thisfday,&thisftime); if (rc != 0) return(0); if (GridRequest->f_day != thisfday) return(0); } if (GridRequest->f_time != -1) { rc = GetForecastDayTime (GridHeader[3],GridHeader[4],GridHeader[5],&thisfday,&thisftime); if (rc != 0) return(0); if (GridRequest->f_time != thisftime/10000) return(0); } /* Check for src of grid...this is an array of strings */ /* Check for parameter of grid...this is an array of strings */ /* Check for ensemble of grid...this is an array of strings */ /* if (M0GribGridCompare /* check the grib ensemble #s (GridRequest->n_ens,GridRequest->ens,GridHeader[19]) == 0) { if (GridRequest->n_ens == 1 && GridRequest->ens[0] == -1 && GridHeader[19] <= 0) { M0sxtrce("do not want ensemble"); } else { M0sxtrce("GRIB ensemble did not match"); return(0); } } */ if (GridRequest->n_ens > 0) { match = 0; for (i=0; i < GridRequest->n_ens ; i++) { GridString.idata = GridHeader[19]; GridString.cdata[4] = 0; for (j = 3; j > 0; j--) { /* snip off trailing blanks */ if (GridString.cdata[j] == 32 ) { /* i.e., a blank */ GridString.cdata[j] = 0; } else { break; } } if (strcmp(GridString.cdata,GridRequest->ens[i]) == 0) match = 1; } if (match == 0) { M0sxtrce("No match in ensemble"); return(0); } } if (GridRequest->n_src > 0) { match = 0; for (i=0; i < GridRequest->n_src ; i++) { GridString.idata = GridHeader[32]; GridString.cdata[4] = 0; for (j = 3; j > 0; j--) { /* snip off trailing blanks */ if (GridString.cdata[j] == 32 ) { /* i.e., a blank */ GridString.cdata[j] = 0; } else { break; } } if (strcmp(GridString.cdata,GridRequest->source[i]) == 0) match = 1; } if (match == 0) { M0sxtrce("No match in source"); return(0); } } M0sxtrce("check parameter"); if (GridRequest->n_parm > 0) { match = 0; for (i=0; i < GridRequest->n_parm ; i++) { GridString.idata = GridHeader[6]; GridString.cdata[4] = 0; for (j = 3; j > 0; j--) { if (GridString.cdata[j] == 32 ) { /* i.e., a blank */ GridString.cdata[j] = 0; } else { break; } } (void)sprintf(gribdbg,"Parameter compare >%s< and >%s< ",GridString.cdata, GridRequest->parm[i]); M0sxtrce(gribdbg); if (strcmp(GridString.cdata,GridRequest->parm[i]) == 0) { match = 1; } } if (match == 0) { M0sxtrce("No match in parameter"); return(0); } } /* the check for levels is complicated....the stuff in GridHeader ** is McIDAS-standard, so there are levels and special values ** (SFC, MSL, TROP, for example). Or there can be integer ** representations of the character strings (lit('MAXW'), for example). ** Check against all these, and also the level units. 100 mb != 100 ft ** Each of the structure values in GridRequest for the level should have ** a character string value..and a double precision value as well ** if it's a number. */ match = 0; if (GridRequest->n_level > 0) { for (i = 0; i < GridRequest->n_level ; i++) { (void)sprintf(gribdbg,"i is %d out of %d %f ",i,GridRequest->n_level, (double)GridRequest->d_level[0]); M0sxtrce(gribdbg); (void)sprintf(gribdbg," Request level is %f ",GridRequest->d_level[i]); M0sxtrce(gribdbg); if (GridRequest->d_level[i] == -1) { /* compare the char string */ memcpy(&LevelStr[0],&GridHeader[9],(size_t)4); LevelStr[4] = 0; M0sxtrce(LevelStr); M0sxtrce(GridRequest->c_level[i]); if (strcmp(GridRequest->c_level[i],LevelStr) == 0) match = 1; memcpy(&LevelUnit[0],&GridHeader[11],(size_t)4); LevelUnit[4] = 0; M0sxtrce(LevelUnit); if (VecLen(GridRequest->u_level) > 0) { M0sxtrce("Is there a match in level unit"); if (strcmp(GridRequest->u_level[i],LevelUnit) != 0) match = 0; } } else { /* compare numeric values, which may *** be scaled... */ if (GridRequest->d_level[i] != 0) { M0sxtrce("Compute gridvalue"); GridValue = GridHeader[9]*pow(10.,(double)GridHeader[10]); (void)sprintf(gribdbg,"Values: %f %f %d ",GridValue,GridRequest->d_level[i],i); M0sxtrce(gribdbg); if (GridValue == GridRequest->d_level[i]) match = 1; /* check level unit */ if (match == 1 && VecLen(GridRequest->u_level) > 0) { strtofs((char *)&LevelUnit[0],(char *)&GridHeader[11],4); LevelUnit[4] = 0; (void)sprintf(gribdbg,"Test level Unit is %d >%s<",i,GridRequest->u_level[0]); M0sxtrce(gribdbg); (void)sprintf(gribdbg,"Level Unit is >%s< ",LevelUnit); M0sxtrce(gribdbg); for (ii = 4; ii >= 0; ii--) { (void)sprintf(gribdbg,"Character %d is %x ",ii,LevelUnit[ii]); M0sxtrce(gribdbg); if (LevelUnit[ii] == (char)32) LevelUnit[ii] = (char)0; if (LevelUnit[ii] != (char)32 && LevelUnit[ii] != (char)0) ii=0; } /* if level unit doesn't match, then neither does the grid */ if (GridRequest->u_level[i] != NULL && LevelUnit != 0) { if (strcmp(GridRequest->u_level[i], LevelUnit) != 0) match = 0 ; } if (match == 1) M0sxtrce("FOUND MATCH"); } } else { /* check for special cases */ (void)sprintf(gribdbg,"Special case for request: >%s<", GridRequest->c_level[0]); M0sxtrce(gribdbg); match = M0GribCheckSpecialCase(GridRequest->c_level[0], GridHeader[9]); /* check level */ if (VecLen(GridRequest->u_level) > 0) { (void)sprintf(gribdbg,"Unit Level: %x ",GridRequest->u_level); M0sxtrce(gribdbg); (void)sprintf(gribdbg,"Unit Level: %x ",GridRequest->u_level[0]); M0sxtrce(gribdbg); strtofs((char *)&LevelUnit[0],(char *)&GridHeader[11],4); LevelUnit[4] = 0; for (ii = 4; ii >= 0; ii--) { (void)sprintf(gribdbg,"Character %d is %x ",ii,LevelUnit[ii]); M0sxtrce(gribdbg); if (LevelUnit[ii] == (char)32) LevelUnit[ii] = (char)0; if (LevelUnit[ii] != (char)32 && LevelUnit[ii] != (char)0) ii=0; } /* if level unit doesn't match, then neither does the grid */ (void)sprintf(gribdbg,"Check >%s< vs. >%s< ", GridRequest->u_level[i],LevelUnit); M0sxtrce(gribdbg); if (GridRequest->u_level != NULL && LevelUnit != 0) { if (strcmp(GridRequest->u_level[i], LevelUnit) != 0) match = 0 ; } M0sxtrce("Check done"); } } } } if (match == 0) { M0sxtrce("no match in level"); return(0); /* didn't match, so error out */ } } if (GridRequest->n_proj > 0) { match = 0; for (i = 0; i < GridRequest->n_proj ; i++) { M0sxtrce(GridRequest->proj[i]); if ( ( (strcmp(GridRequest->proj[i],"MERC") == 0) && (GridHeader[33] == 1 || GridHeader[33] == 4) ) || ( (strcmp(GridRequest->proj[i],"LAMB") == 0) && (GridHeader[33] == 6) ) || ( (strcmp(GridRequest->proj[i],"PS") == 0) && (GridHeader[33] == 2) ) || ( (strcmp(GridRequest->proj[i],"CONF") == 0) && (GridHeader[33] == 6 || GridHeader[33] == 2) ) || ( (strcmp(GridRequest->proj[i],"EQUI") == 0) && (GridHeader[33] == 3 ) ) || ( GridHeader[33] == 5 ) ) match = 1; } if (match == 0) { M0sxtrce("no match in projection"); return(0); /* didn't match, so error out */ } } return(1); } /* *$ Name: *$ M0GribGridCompare -- compare Request structure values and Grid Header *$ value *$ *$ Interface: *$ int M0GribGridCompare(int nvals, int *vals, int gridval) *$ *$ Input: *$ nvals - number of values in vals *$ vals - array of values or a single value *$ gridval - Grid header value *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 1 - matched value *$ 0 - did not match value *$ *$ Remarks: *$ Get the McIDAS grid header from the GribGrid_Header structure *$ *$ Categories: *$ grid */ int M0GribGridCompare ( int nvals, int *vals, int gridval) { int i; if (nvals <= 0) return(1); for ( i = 0; i < nvals; i++) { if (vals[i] == gridval) return(1); } return(0); } /* *$ Name: *$ M0MatchListuv -- See if a v-grid matches a u-grid *$ *$ Interface: *$ int M0MatchListuv(GribGrid ** StructAddress, int * uGridHead) *$ *$ Input: *$ Top - linked list including grid headers *$ uGridHead - Grid Header of u grid *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ -1 - malloc failure *$ 0 - no matching v grid exists *$ 1 - Found a matching v grid *$ *$ Remarks: *$ See if a Grid header matches a v-grid on the stack *$ *$ Categories: *$ grid */ int M0MatchListuv ( GribGrid_Header ** Structures, Fint * GHead) { GribGrid_Header * ThisGribGrid; int match = 1; /* assume they all match! */ Fint VHead[64]; int i; int ok; i = 0; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (ThisGribGrid == NULL) return(-1); /* the two grids 'match' if the day/time/fhour/size are equal, and ** all the projection parameters also */ while (Structures[i] != (GribGrid_Header *)NULL) { /* i.e., a valid address */ int tint; char tstr[5]; memcpy( (void *)ThisGribGrid, (void *)Structures[i], sizeof(GribGrid_Header)); tint = ThisGribGrid->MCGRIDHEADER[6]; memcpy(&tstr[0],&tint,sizeof(int)); tstr[4] = 0; if (strcmp(tstr,"V ") == 0 || /* found a v grid -- */ strcmp(tstr,"V") == 0 || strcmp(tstr," V") == 0) { /** see if it matches */ ok = M0GribGetGridHeader(ThisGribGrid,&VHead[0]); match = M0CompareGridHeaduv((int *)GHead,(int *)&VHead[0], ThisGribGrid->GribType); if (match == 1) { /* Found a match, we can return */ M0sxtrce("FOUND A MATCH!"); return(match); } } i++; } free(ThisGribGrid); return(match); } /* *$ Name: *$ M0CompareGridHead -- See if 2 grids match *$ *$ Interface: *$ int M0CompareGridHead(int * GridHead, int * GridHead, int GribType) *$ *$ Input: *$ GridHead - Grid header, grid 1 *$ GridHead - Grid Header, grid 2 *$ GribType - Grib1 or Grib2 data? *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - grids don't match *$ 1 - grids match *$ *$ Remarks: *$ See if 1 Grid header matches another -- i.e., parameter may *$ differ, but the rest doesn't...don't compare grib parameters *$ for grib2 data *$ *$ Categories: *$ grid */ int M0CompareGridHead(int * McGridHdr1,int * McGridHdr2, int GribType) { int i; int matchpoints[]={0,1,2,3,4,5, /* size and day/time information */ 9,11,12,13,14, /* vertical level types */ 19, /* ens number */ 33,34,35,36,37,38,39, /* projection values */ 49,50,51 }; /* GRIB values (grib geo # ignored */ int nmatchpoints; nmatchpoints = sizeof(matchpoints)/sizeof(int); for (i = 0; i < nmatchpoints ; i++) { if (matchpoints[i] > 48 && GribType == 2) break; if (McGridHdr1[matchpoints[i]] != McGridHdr2[matchpoints[i]]) { (void)sprintf(gribdbg,"Failed to match at slot %d %d %d ", matchpoints[i],McGridHdr1[matchpoints[i]], McGridHdr2[matchpoints[i]]); M0sxtrce(gribdbg); if ( (matchpoints[i] == 34 || matchpoints[i] == 35) && (McGridHdr1[33] == 2 || McGridHdr1[33] == 6) ) { float Value1 = McGridHdr1[matchpoints[i]]/10000.; float Value2 = McGridHdr2[matchpoints[i]]/10000.; float pct = (fabs((Value1-Value2)/Value1))*100.; if (pct > 1.) { return(0); } else { M0sxtrce("But Values are close enough"); } } else { return(0); } } } /* note that if the geographic grib numbers differ, then the sizes ** of the grid will differ and the comparison will fail there */ M0sxtrce("Golly -- these grids match!"); return(1); } /* *$ Name: *$ M0CompareGridHeaduv -- See if a u-grid matches a v-grid *$ *$ Interface: *$ int M0CompareGridHeaduv(int * uGridHead, int * vGridHead, int GribType) *$ *$ Input: *$ uGridHead - Grid header, grid 1 *$ vGridHead - Grid Header, grid 2 *$ GribType - Grib1 or Grib2? *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - grids don't match *$ 1 - grids match *$ *$ Remarks: *$ See if 1 Grid header matches another -- i.e., parameter may *$ differ, but the rest doesn't. This function is just like *$ M0CompareGridHead except it ignored differences in slot 49 *$ *$ Categories: *$ grid */ int M0CompareGridHeaduv(int * McGridHdr1,int * McGridHdr2, int GribType) { int i; int matchpoints[]={0,1,2,3,4,5, /* size and day/time information */ 9,10,11,12,13,14, /* vertical level types */ 19, /* ensemble number */ 33,34,35,36,37,38,39, /* projection values */ 50,51}; /* GRIB values (grib geo # , par # ignored */ int nmatchpoints; nmatchpoints = sizeof(matchpoints)/sizeof(int); for (i = 0; i < nmatchpoints ; i++) { if (matchpoints[i] >=50 && GribType == 2) break; if (McGridHdr1[matchpoints[i]] != McGridHdr2[matchpoints[i]]) { (void)sprintf(gribdbg," Failed to match: %d %d %d %d ",matchpoints[i], McGridHdr1[matchpoints[i]], McGridHdr2[matchpoints[i]],McGridHdr1[33]); M0sxtrce(gribdbg); if ( (matchpoints[i] == 34 || matchpoints[i] == 35) && (McGridHdr1[33] == 2 || McGridHdr1[33] == 6) ) { float Value1 = McGridHdr1[matchpoints[i]]/10000.; float Value2 = McGridHdr2[matchpoints[i]]/10000.; float pct = (fabs((Value1-Value2)/Value1))*100.; if (pct > 1.) { return(0); } else { M0sxtrce("But Values are close enough"); } } else { return(0); } } } /* note that if the geographic grib numbers differ, then the sizes ** of the grid will differ and the comparison will fail there */ return(1); } /* *$ Name: *$ M0GribGetGridvData -- get v grid data from a GRIB file that matches u *$ data *$ *$ Interface: *$ int M0GribGetGridvData( GribGrid_Header ** StructAddress, *$ int * LastInStitch, *$ Fint * McGridData, Fint * McGridHeaderu, *$ Fint * McGridHeaderv) *$ *$ Input: *$ StructAddress - list of structure addresses *$ LastInStitch - flag saying if it's the last of a series of grids *$ McGridHeaderu - 64-word grid header of u grid *$ *$ Input and Output: *$ none *$ *$ Output: *$ McGridData - scaled integer gridded arrary *$ McGridHeaderv - 64-word grid header of matching v data *$ *$ Return values: *$ 0 - success *$ -5 - Failed to open GRIB file *$ -6 - fseek failure on file *$ -7 - malloc error *$ -10 - mcgrb2mc failure -- did not convert from GRIB to McGrid *$ -15 - retrieved grid header different from stored gridheader *$ *$ Remarks: *$ Open the GRIB file indicated in the GribGrid_Header structure, *$ and read in the number of bytes of data starting at the offset, *$ also both indicated in the structure. Then convert the GRIB *$ data to a McIDAS grid and return the grid and grid header *$ *$ Categories: *$ grid */ int M0GribGetGridvData( GribGrid_Header ** AddressIndex, int * LastInStitch, Fint * McGridDat, Fint * McGridHdru, Fint * McGridHdrv) { Fint * McHeader1; /* 64-words grid header */ Fint * McHeader2; /* 64-words grid header */ Fint * McGridData = NULL; /* scaled integer gridded data */ GribGrid_Header * ThisGribGrid = NULL; int i,j,k; /* loop control */ int iret; int missing; /* int rc;*/ int gridsize; /* um..size of the grid described in gridheader */ int tint; /* temporary integer */ int FirstStitch,LastStitch; char tstr[5]; /* temporary string holder */ missing = 0x80808080; FirstStitch = 255; LastStitch = 0; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); McHeader1 = (Fint *)malloc(sizeof(int)*HEDSIZ); McHeader2 = (Fint *)malloc(sizeof(int)*HEDSIZ); if (ThisGribGrid == NULL || McHeader1 == NULL || McHeader2 == NULL) return(-7); /* Find the matching header */ i = 0; while (AddressIndex[i] != (GribGrid_Header *)NULL) { /* a valid address */ memcpy( (void *)ThisGribGrid, (void *)AddressIndex[i], sizeof(GribGrid_Header)); iret = M0GribGetGridHeader(ThisGribGrid,McGridHdrv); (void)sprintf(gribdbg, "GribGetGridvData Get GribGetGridHeader[19] is %d ",McGridHdrv[19]); M0sxtrce(gribdbg); tint = McGridHdrv[6]; memcpy(&tstr[0],&tint,sizeof(int)); tstr[4] = 0; if (strcmp(tstr,"V ") == 0 || /* see if the v grid matches */ strcmp(tstr,"V") == 0 || strcmp(tstr," V") == 0) { (void)sprintf(gribdbg,"does v grid in slot %d match?",i); M0sxtrce(gribdbg); if (M0CompareGridHeaduv(McGridHdru,McGridHdrv,ThisGribGrid->GribType) == 1) { int countgrids = 1; M0sxtrce("YES!... Found a matching v grid to send back"); (void)memcpy((void *)McHeader1,(void *)McGridHdrv,sizeof(Fint)*HEDSIZ); gridsize = McHeader1[0]; (void)sprintf(gribdbg,"SIze of v grid is %d ",McHeader1[0]); M0sxtrce(gribdbg); McGridData = (Fint *)malloc(gridsize*sizeof(Fint));/*4-byte words */ if (McGridData == (Fint *)NULL) { (void)sprintf(gribdbg, "Failed to malloc space for McIDAS grid of size %d", gridsize); M0sxtrce(gribdbg); return(-7); } M0sxtrce("Get the v grid[s]!"); iret = M0GribReadGridData(ThisGribGrid,McGridData,McHeader1); (void)sprintf(gribdbg,"SIze of v grid is %d ",McHeader1[0]); M0sxtrce(gribdbg); memcpy((void *)McHeader2,(void *)McHeader1,(size_t)256); j = i; while (LastInStitch[j] == 0) { /* Stitch */ Fint * McGridData2 = NULL; if (McHeader2[48] > LastStitch) LastStitch = McHeader2[48]; if (McHeader2[48] < FirstStitch) FirstStitch = McHeader2[48]; (void)sprintf(gribdbg,"J is %d, Firststitch %d last %d ", j,FirstStitch,LastStitch); M0sxtrce(gribdbg); memcpy( (void *)ThisGribGrid, (void *)AddressIndex[j], sizeof(GribGrid_Header)); iret = M0GribGetGridHeader(ThisGribGrid,(void *)McHeader2); if (McHeader2[48] > LastStitch) LastStitch = McHeader2[48]; if (McHeader2[48] < FirstStitch) FirstStitch = McHeader2[48]; if (countgrids > 1) { McGridData2 = (Fint *)malloc(sizeof(Fint)*McHeader1[0]); if (McGridData2 == NULL) return(-7); /* Grab all the grib data and paste them together */ iret = M0GribReadGridData(ThisGribGrid,McGridData2,McHeader2); (void)sprintf(gribdbg,"GribReadGridData (2) returns %d ",iret); M0sxtrce(gribdbg); if (iret < 0) { free(McGridData); return(iret); } (void)sprintf(gribdbg,"save data for Grib Geo Parameter %d ", McHeader2[48]); M0sxtrce(gribdbg); for (k = 0; k < McHeader2[0]; k++) { if (McGridData2[k] != missing) { McGridData[k] = McGridData2[k]; } } free(McGridData2); } countgrids++; j++; } /* Now grab the last in the series of stitchable grids */ if (countgrids > 1 && LastInStitch[j] == 1) { Fint * McGridData2 = NULL; memcpy( (void *)ThisGribGrid, (void *)AddressIndex[j], sizeof(GribGrid_Header)); iret = M0GribGetGridHeader(ThisGribGrid,(void *)McHeader2); if (McHeader2[48] > LastStitch) LastStitch = McHeader2[48]; if (McHeader2[48] < FirstStitch) FirstStitch = McHeader2[48]; McGridData2 = (Fint *)malloc(sizeof(Fint)*McHeader1[0]); if (McGridData2 == NULL) return(-7); /* Paste in the newly - acquired data */ iret = M0GribReadGridData(ThisGribGrid,McGridData2,McHeader2); (void)sprintf(gribdbg,"GribReadGridData (3) returns %d ",iret); M0sxtrce(gribdbg); if (iret < 0) { free(McGridData); return(iret); } (void)sprintf(gribdbg,"save data for Grib Geo Parameter %d ", McHeader2[48]); M0sxtrce(gribdbg); for (k = 0; k < McHeader2[0]; k++) { if (McGridData2[k] != missing) { McGridData[k] = McGridData2[k]; } } free(McGridData2); } if (iret < 0) { free(McGridData); return(iret); } M0sxtrce("Move the data over"); memcpy( (void *)McGridDat,(void *)McGridData, sizeof(int)*McHeader1[0]); memcpy( (void *)McGridHdrv,(void *)&McHeader1[0],(size_t)256); break; } } i++; } free(ThisGribGrid); free(McGridData); free(McHeader1); free(McHeader2); M0sxtrce("Return the data"); return(0); } /* *$ Name: *$ M0GribReadGridData -- get grid data from a GRIB file *$ *$ Interface: *$ int M0GribReadGridData( GribGrid_Header * Valid, Fint * McGridData, *$ Fint * McGridHeader) *$ *$ Input: *$ Valid - Linked list of GRIB/grid data...top node has info *$ on the GRIB file to read *$ *$ Input and Output: *$ none *$ *$ Output: *$ McGridData - scaled integer gridded arrary *$ McGridHeader - 64-word grid header *$ *$ Return values: *$ 0 - success *$ -5 - Failed to open GRIB file *$ -7 - malloc error *$ -10 - mcgrb2mc failure -- did not convert from GRIB to McGrid *$ -15 - retrieved grid header different from stored gridheader *$ *$ Remarks: *$ Open the GRIB file indicated in the GribGrid_Header structure, *$ and read in the number of bytes of data starting at the offset, *$ also both indicated in the structure. Then convert the GRIB *$ data to a McIDAS grid and return the grid and grid header *$ *$ Categories: *$ grid */ int M0GribReadGridData( GribGrid_Header * Valid, Fint * McGridDat, Fint * McGridHdr) { Fint McHeader1[HEDSIZ]; /* 64-words grid header */ Fint McHeader2[HEDSIZ]; /* 64-words grid header */ Fint * McGridData = NULL; /* scaled integer gridded data */ Fint * McGrib2Header = NULL; /* Grib2 header */ char * Buffer = NULL; /* buffer to hold GRIB data */ FILE *F1; /* handle for open file */ char tchar[5]; int allmatch; int i; /* loop control */ int one=1; int rc; int gridsize; /* um..size of the grid described in gridheader */ Fint maxbytesize; Fint PoleFlag; Fint OrigProj; gridsize = Valid->MCGRIDHEADER[0]; for (i=0;iMCGRIDHEADER[i]; (void)sprintf(gribdbg,"Pass into GribReadGridData McHeader1[19] of %d", McHeader1[19]); M0sxtrce(gribdbg); (void)sprintf(gribdbg,"Open up file >%s< to READ %d data %d %d",Valid->GRIBFileName, gridsize,sizeof(Fint)*gridsize,McHeader1[11]); M0sxtrce(gribdbg); McGridData = (Fint *)malloc(sizeof(Fint)*gridsize*4); if (McGridData == NULL) return(-7); F1 = fopen(Valid->GRIBFileName,"r"); if (F1 == (FILE *) NULL) { (void)sprintf(gribdbg,"Could not open GRIB data file %s ", Valid->GRIBFileName); M0sxtrce(gribdbg); free(McGridData); return(-5); } switch (Valid->GribType) { case 1 : rc = fseek(F1,Valid->byteoffset,SEEK_SET); if (rc < 0) { (void)sprintf(gribdbg,"Failed in fseek (%d) in file %s", Valid->byteoffset,Valid->GRIBFileName); M0sxtrce(gribdbg); return(-6); } Buffer = (char *)malloc(Valid->GRIBsize); if (Buffer == (char *) NULL ) { (void)sprintf(gribdbg,"Failed to make GRIB buffer of size %d", Valid->GRIBsize); M0sxtrce(gribdbg); return(-7); } rc = fread((void *) Buffer, one, (size_t) Valid->GRIBsize, F1); if (rc < Valid->GRIBsize) { M0sxtrce("WARNING: Did not read in all the bytes requested..."); } (void)fclose(F1); maxbytesize = gridsize*4; (void)sprintf(gribdbg,"Call mcgrb2mc -- put data in address %x %x %d \n", McGridData,&McGridData[0],McHeader1[11]); M0sxtrce(gribdbg); rc = (int) mcgrb2mc_((void*)Buffer,(Fint *)&Valid->GRIBsize, &McHeader2[0],&McGridData[0], &maxbytesize,&PoleFlag,&OrigProj,NULL,0); (void)sprintf(gribdbg,"Called mcgrb2mc -- %d %d \n", McHeader2[11],McHeader1[11]); M0sxtrce(gribdbg); if (rc < 0) { (void)sprintf(gribdbg,"mcgrb2mc returns %d...Failure!",rc); M0sxtrce(gribdbg); free(Buffer); free(McGridData); if (rc == -1011) return(-1011); return(-10); } free(Buffer); /* all done with it now */ break; case 2 : (void)fclose(F1); McGrib2Header = (Fint *)malloc(sizeof(Fint)*64); if (McGrib2Header == NULL) { free(McGridData); return(-7); } rc = M0Grib2McData(Valid,&McGrib2Header,&McGridData); (void)sprintf(gribdbg,"Called M0Grib2McData -- %d %d \n", McGrib2Header[19],McHeader1[19]); M0sxtrce(gribdbg); if (rc < 0) { free(McGridData); free(McGrib2Header); M0sxtrce("Failed in decode"); return(-10); } (void)sprintf(gribdbg,"M0Grib2McData returned %d \n",rc); M0sxtrce(gribdbg); memcpy((void *)&McHeader2[0],(void *)McGrib2Header,(size_t)256); (void)sprintf(gribdbg,"Got Header2 values %d ", McGrib2Header[19]); M0sxtrce(gribdbg); free(McGrib2Header); break; default : (void)sprintf(gribdbg,"Unknown grib type: %d",Valid->GribType); M0sxtrce(gribdbg); free(McGridData); return(-10); break; } /* if McHeader1 and McHeader2 are not the same, something ** is seriously hosed, unless it's slot 16, the "grid" number ** which is set in the server... Also ignore slots 46,47 */ allmatch = 1; for (i = 0 ; i < HEDSIZ; i++) { char c1[5],c2[5]; if ( (McHeader1[i] != McHeader2[i]) && i!= 9 && i != 16 && i != 46 && i != 47 && i < 60 && i != 7 && i != 10 && (Valid->GribType == 2 && ( i < 48 || i > 51)) ) { /* allow for a little error in the Row/Col N. Pole to account for ** as-yet unexplained discrepancy between server value and database ** value...1 percent */ (void)sprintf(gribdbg,"HEY!! Headers are different %d %d %d ", i,McHeader1[i],McHeader2[i]); M0sxtrce(gribdbg); if ( (i == 34 || i == 35) && (McHeader1[33] == 2 || McHeader1[33] == 6) ) { float Value1 = McHeader1[i]/10000.; float Value2 = McHeader2[i]/10000.; float pct = (fabs((Value1-Value2)/Value1))*100.; if (pct > 1.) { allmatch = 0; } else { M0sxtrce("But Values are close enough"); } } else { if (i < 52) { allmatch=0; break; } } } } memcpy((void *)&tchar[0],(void *)&McHeader2[6],(size_t)4); tchar[4] = 0; (void)sprintf(gribdbg,"McHeader2[6] is: %d %s \n",McHeader2[6],tchar); M0sxtrce(gribdbg); if (allmatch != 1) { free(McGridData); return(-15); } /* move the found data to output */ (void)sprintf(gribdbg,"Move %d data points to output %x",McHeader1[0],McGridDat); M0sxtrce(gribdbg); memcpy( (void *)McGridDat, (void *)McGridData,sizeof(int)*McHeader1[0]); memcpy( (void *)McGridHdr, (void *)&McHeader2[0],(size_t)256); /* free(McGridData); */ return(0); } /* *$ Name: *$ M0GribGetGridvHeader -- get v grid header from a GRIB file that *$ matches u header *$ *$ Interface: *$ int M0GribGetGridvHeader( GribGrid_Header ** StructAddress, *$ Fint * McGridHeaderu, Fint * McGridHeaderv) *$ *$ Input: *$ StructAddress - array of addresses to GribGrid_Header structures *$ GD - GridDerive structure *$ McGridHeaderu - 64-word grid header of u grid *$ *$ Input and Output: *$ none *$ *$ Output: *$ McGridHeaderv - 64-word grid header of matching v grid *$ *$ Return values: *$ 0 - success *$ -5 - Failed to open GRIB file *$ -6 - fseek failure on file *$ -7 - malloc error *$ -15 - retrieved grid header different from stored gridheader *$ *$ Remarks: *$ Open the GRIB file indicated in the GribGrid_Header structure, *$ and read in the header that matches the u grid *$ *$ Categories: *$ grid */ int M0GribGetGridvHeader( GribGrid_Header ** StructIndex, Fint * McGridHdru, Fint * McGridHdrv) { /* Fint McHeader1[HEDSIZ];*/ /* 64-words grid header */ Fint McHeader2[HEDSIZ]; /* 64-words grid header */ GribGrid_Header * Top = NULL; int i; /* loop control */ int iret; /* int rc; int gridsize; */ /* um..size of the grid described in gridheader */ int tint; char tstr[5]; Top = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (Top == NULL) return(-7); /* Find the matching header */ i = 0; (void)sprintf(gribdbg,"getGridvHEader i is %d Struct is %p ",i,StructIndex[i]); M0sxtrce(gribdbg); while (StructIndex[i] != (GribGrid_Header *) NULL ) { memcpy( (void *)Top, (void *)StructIndex[i],sizeof(GribGrid_Header)); iret = M0GribGetGridHeader(Top,&McHeader2[0]); (void)sprintf(gribdbg," Returned %d %d %d %d %d %d %d %d ", McHeader2[0],McHeader2[1],McHeader2[2],McHeader2[9], McHeader2[48],McHeader2[49],McHeader2[50],McHeader2[51]); M0sxtrce(gribdbg); /* make sure the grid you got is a 'v' grid */ tint = McHeader2[6]; memcpy(&tstr[0],&tint,sizeof(int)); tstr[4] = 0; if (strcmp(tstr,"V ") == 0 || /* see if the v grid matches */ strcmp(tstr,"V") == 0 || strcmp(tstr," V") == 0) { if (M0CompareGridHeaduv(McGridHdru,&McHeader2[0],Top->GribType) == 1) { for (i = 0 ; i < HEDSIZ ; i++) { McGridHdrv[i] = McHeader2[i]; (void)sprintf(gribdbg,"FOUND MATCH move header %d %d %d", i,McGridHdrv[i],McHeader2[i]); M0sxtrce(gribdbg); } break; } } i++; } free(Top); return(0); } /* *$ Name: *$ M0PrintSizes - print the sizes of Grids in the stack *$ *$ Interface: *$ int M0PrintSizes( GribGrid_Header *ValidGribFiles) *$ *$ Input: *$ ValidGribFiles - linked list including grid headers *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - success *$ *$ Remarks: *$ Go through the GribGrid_Header structure and print out grid sizes *$ for debug *$ *$ Categories: *$ grid */ int M0PrintSizes( GribGrid_Header *Valid) { int cnt = 0; GribGrid_Header * Top = NULL; Top = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (Top == NULL) return(-20); Top = Valid; while (Top != NULL) { (void)sprintf(gribdbg,"cnt %d size %d",cnt,Top->MCGRIDHEADER[0]); M0sxtrce(gribdbg); cnt++; Top = Top->nextGribGrid; } return(0); } /* *$ Name: *$ M0IsPartialGrib - see if more grib files are needed *$ to make a complete set *$ *$ Interface: *$ int *$ M0IsPartialGrib(Fint * GHeader, int slot, GridRequestObj * GridR, *$ int * ThisGrib, int * StartGrib, int * EndGrib ) *$ *$ Input: *$ GHeader - McIDAS grid header of data found *$ slot - where in header to check for matching values *$ GridR - Grid Request object -- contains sort conditions *$ *$ Input and Output: *$ none *$ *$ Output: *$ ThisGrib - grib file number of passed-in grid *$ StartGrib - start value of matching set *$ EndGrib - end value of matching set *$ *$ Return values: *$ <-100 - failure ... bad slot number *$ -1 - failure....time to abort! *$ 0 - don't get any more data *$ 1 - need to get more data *$ *$ Remarks: *$ Returns the string that is used by the SQL database to find *$ data that matches the sort conditions *$ Note that for now, slot must equal 48 (Geographic grib number *$ slot in the McIDAS grid header). If a slot other than that *$ is specified, -(100+slot) is returned *$ *$ Categories: *$ utility */ int M0IsPartialGrib(Fint * GHeader, int slot, GridRequestObj * GridR, int * ThisGrib, int * BeginGrib, int * EndGrib) { int BGrib, EGrib; /* begin grib value, end grib value */ int ok; /* function return values */ int ThisValue; int ThisSlot; *ThisGrib = -1; /* initialize return variables */ *BeginGrib = -1; *EndGrib = -1; if (slot != 48) return(-(100+slot)); /* Note that if any specific grib= is requested, or if a series ** of *specific* grib= are requested, you don't want to do ** any stitching...Test for that eventuality in the switch */ M0sxtrce("Call FINDgRIBrANGe"); ThisValue = GHeader[slot]; ThisSlot = slot; (void)sprintf(gribdbg,"Call FindGribRange with value %d in slot %d", ThisValue,ThisSlot); M0sxtrce(gribdbg); ok = M0FindGribRange(ThisValue,ThisSlot,&BGrib,&EGrib); *BeginGrib = BGrib; *EndGrib = EGrib; if (ok != 0) return(0); if ( BGrib == 37 && EGrib == 44 && GridR->n_gribgeo > 0 && GridR->n_gribgeo !=8) return(0); if ( BGrib == 21 && EGrib == 24 && GridR->n_gribgeo > 0 && GridR->n_gribgeo !=4) return(0); if ( BGrib == 61 && EGrib == 64 && GridR->n_gribgeo > 0 && GridR->n_gribgeo !=4) return(0); if ( BGrib == 25 && EGrib == 26 && GridR->n_gribgeo > 0 && GridR->n_gribgeo !=2) return(0); if ( GHeader[50] == 126 && (BGrib == 1 && EGrib == 12 && GridR->n_gribgeo > 0 && GridR->n_gribgeo !=8) ) return(0); if ( GHeader[50] == 126 && (BGrib == 5 && EGrib == 8 && GridR->n_gribgeo > 0 && GridR->n_gribgeo !=4) ) return(0); /* Having exhausted all the ways we can return false, return true */ return(1); } /* *$ Name: *$ M0FindGribRange -- given a slot, return the matching values *$ required to create a global grid *$ *$ Interface: *$ int *$ M0FindGribRange(int Value, int slot, int *Start, int *End) *$ *$ Input: *$ Value - value in McIDAS grid header *$ slot - where in header Value occurs *$ *$ Input and Output: *$ none *$ *$ Output: *$ Start - start value of matching set *$ End - end value of matching set *$ *$ Return values: *$ <-100 - failure ... bad slot number *$ 0 - success *$ *$ Remarks: *$ Returns the grib values needed to complete a set *$ Note that for now, slot must equal 48 (Geographic grib number *$ slot in the McIDAS grid header). If a slot other than that *$ is specified, -(100+slot) is returned *$ *$ Categories: *$ utility */ int M0FindGribRange(int Value, int slot, int *start, int *end) { *start = -1; *end = -1; if (slot != 48) return (-(100+slot)); (void)sprintf(gribdbg,"FindGribRange with value %d from slot %d", Value,slot); M0sxtrce(gribdbg); switch (Value) { case 3744: case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: *start = 37; *end = 44; return(0); break; case 2124: case 21: case 22: case 23: case 24: *start = 21; *end = 24; return(0); break; case 2526: case 25: case 26: *start = 25; *end = 26; return(0); break; case 6164: case 61: case 62: case 63: case 64: *start = 61; *end = 64; return(0); break; case 14912: case 1: case 2: case 3: case 4: case 9: case 10: case 11: case 12: *start = 1; *end = 12; return(0); break; case 5678: case 5: case 6: case 7: case 8: *start = 5; *end = 8; return(0); break; default: return(-1); } } /* *$ Name: *$ M0ReorderList -- Drop through the GribGrid structure and pair *$ up all the matching files *$ *$ Interface: *$ int M0ReorderList( GribGrid_Header ** ValidGribFiles, *$ GridRequestObj * Request, int ngrids_to_get) *$ *$ Input: *$ ngrids_to_get - number of grids requested of the server *$ Request - Grid Request Object *$ *$ Input and Output: *$ ValidGribFiles - on input, the un-ordered set of GribFiles *$ on output, the structure has been ordered *$ so that stitchable structures are sequential *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - success *$ -1 - file does not contain GRIB data *$ -2 - malloc failure *$ -10 - file software errors (fopen or fstat) *$ -12 - Failure in M0GribMakeGridHeader *$ -100 - Too Many Grids *$ *$ Remarks: *$ This function scans through the linked list in the GribGrid_Header *$ structure and puts the files to be combined (for thinned grids) *$ in sequential order *$ Only the first ngrids_to_get'th GribGrid_Header structures are *$ reordered. *$ *$ Categories: *$ grid */ int M0ReorderList(GribGrid_Header ** ValidGribFiles, GridRequestObj *Request, int ngrids_to_get) { GribGrid_Header * SortedGribFiles = NULL; GribGrid_Header * ThisGribGrid = NULL; GribGrid_Header * TopNode = NULL; GribGrid_Header * FirstNodeToSendBack = NULL; GribGrid_Header * FinalNodeToSendBack = NULL; GribGrid_Header * TopNewNodeToSendBack = NULL; GribGrid_Header * NewNodeToSendBack = NULL; GribGrid_Header * LastNodeToSendBack = NULL; GribGrid_Header * Searching = NULL; GribGrid_Header * Dummy = NULL; int StructSearch = 0; int GribRequested; int TopGridHeader[64]; int NumberCompleteStackEntries = 0; int MatchFailed = 0; SortedGribFiles = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); TopNode = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); Searching = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); Dummy = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (SortedGribFiles == NULL || ThisGribGrid == NULL || TopNode == NULL || Searching == NULL || Dummy == NULL) return(-2); (void)sprintf(gribdbg,"Valid is %x ",*ValidGribFiles); M0sxtrce(gribdbg); if (*ValidGribFiles == NULL) return(0); memcpy( (void *)TopNode, (void *) *ValidGribFiles,sizeof(GribGrid_Header)); GribRequested = 0; if (Request->n_gribgeo > 0 || Request->grid_ngrid > 0) GribRequested = 1; memcpy( (void *)ThisGribGrid, (void *) TopNode,sizeof(GribGrid_Header)); /* Now, walk through all the found files....We want to put all the matching ** grib files next to each other on the list. That way, the stitching ** can be easily done, and/or the grids that are needed for deriving ** on the client can be sent sequentially */ while (ThisGribGrid != NULL) { (void)sprintf(gribdbg,"ReorderListSource: %d GribRequested: %d \n",ThisGribGrid->MCGRIDHEADER[32], GribRequested); M0sxtrce(gribdbg); if (MatchFailed > 250000) return(-100); if (ThisGribGrid->UsedInSearch == 0 && GribRequested == 0) { if (M0IsStitchable(ThisGribGrid->MCGRIDHEADER[48]) == 1 || M0IsECMFStitchable(ThisGribGrid->MCGRIDHEADER[32],ThisGribGrid->MCGRIDHEADER[48]) == 1) { /* Put onto new stack, and then search for the matching ** structures */ (void)sprintf(gribdbg,"Found a stitchable grid %d ", ThisGribGrid->MCGRIDHEADER[48]); M0sxtrce(gribdbg); memcpy( (void *)&TopGridHeader[0], (void *) &ThisGribGrid->MCGRIDHEADER[0],(size_t)256); ThisGribGrid->UsedInSearch = 1; ThisGribGrid->StitchFlag = 1; ThisGribGrid->LastStructure = 1; TopNewNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); if (TopNewNodeToSendBack == NULL ) return(-2); /* TopNewNodeTo... always contains the Node being built */ LastNodeToSendBack = (GribGrid_Header *)malloc( sizeof(GribGrid_Header)); if (LastNodeToSendBack == NULL) return(-2); (void)sprintf(gribdbg,"Top node to send back: %x ",TopNewNodeToSendBack); M0sxtrce(gribdbg); (void)sprintf(gribdbg,"Last node to send back: %x ",LastNodeToSendBack); M0sxtrce(gribdbg); memcpy ( (void *)TopNewNodeToSendBack,(void *)ThisGribGrid, sizeof(GribGrid_Header)); TopNewNodeToSendBack->prevGribGrid = NULL; TopNewNodeToSendBack->nextGribGrid = NULL; LastNodeToSendBack = TopNewNodeToSendBack; /* start at top of stack, now, and go down, looking for ** structures that match the first one, except for the ** geographic grib number **/ Searching = TopNode; MatchFailed = 0; while (Searching != NULL) { (void)sprintf(gribdbg,"Find matching grid at %x %d %3d %d %d ??", Searching,Searching->UsedInSearch,Searching->MCGRIDHEADER[48], Searching->LastStructure,Searching->StitchFlag); M0sxtrce(gribdbg); if (Searching->UsedInSearch == 0) { if ( M0DiffGeoGrib(Searching,TopNewNodeToSendBack) == 1 ) { /* we have found a file (ThisGribGrid) that matches ** the values in TopGridHeader, but doesn't already ** reside in the TopNewNodeToSendBack stack */ (void)sprintf(gribdbg,"Add to NewNodeToSendBack %x %x %x %d ", TopNewNodeToSendBack,LastNodeToSendBack,Searching, Searching->MCGRIDHEADER[48]); M0sxtrce(gribdbg); Searching->UsedInSearch = 1; Searching->StitchFlag = 1; NewNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); if (NewNodeToSendBack == NULL ) return(-2); memcpy((void *)NewNodeToSendBack,(void *)Searching, sizeof(GribGrid_Header)); NewNodeToSendBack->UsedInSearch = 1; NewNodeToSendBack->StitchFlag = 1; NewNodeToSendBack->LastStructure = 1; LastNodeToSendBack->nextGribGrid = NewNodeToSendBack; LastNodeToSendBack->LastStructure = 0; NewNodeToSendBack->nextGribGrid = NULL; NewNodeToSendBack->prevGribGrid = LastNodeToSendBack; LastNodeToSendBack = NewNodeToSendBack; (void)sprintf(gribdbg," %x Top %x Next %x Last? Top %d Last %d ", NewNodeToSendBack, TopNewNodeToSendBack, TopNewNodeToSendBack->nextGribGrid, TopNewNodeToSendBack->LastStructure, LastNodeToSendBack->LastStructure); M0sxtrce(gribdbg); if (M0NodeComplete(TopNewNodeToSendBack) == 1) { M0sxtrce("Yippy!! FOund a COMPLETE Node "); goto AddStack; } } else { MatchFailed++ ; } } Searching = Searching->nextGribGrid; if (MatchFailed > 250000) break; /* sanity check */ } AddStack: M0sxtrce("Put the Stack on the stack of nodes to send back"); /* now put the (possibly complete, possibly incomplete) stack ** starting at TopNewNodeToSendBack on to the stack starting at ** FirstNodeToSendBack */ if (FirstNodeToSendBack == NULL) { M0sxtrce("malloc the FirstNode"); FirstNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); FinalNodeToSendBack = (GribGrid_Header *)malloc( sizeof(GribGrid_Header)); if (FirstNodeToSendBack == NULL || FinalNodeToSendBack == NULL) return(-2); LastNodeToSendBack->LastStructure = 1; memcpy ( (void *)FirstNodeToSendBack,(void *)TopNewNodeToSendBack, sizeof(GribGrid_Header)); memcpy ( (void *)FinalNodeToSendBack,(void *)LastNodeToSendBack, sizeof(GribGrid_Header)); /* Find the stack entry after TopNewNodeToSendBack and ** point it to FirstNode, not TopNode */ FirstNodeToSendBack->nextGribGrid = TopNewNodeToSendBack->nextGribGrid; /* Find the stack entry before LastNodeToSendBack and ** point it to FinalNode, not LastNode */ Dummy = LastNodeToSendBack->prevGribGrid; if (Dummy != NULL) Dummy->nextGribGrid = FinalNodeToSendBack; FinalNodeToSendBack->prevGribGrid = LastNodeToSendBack->prevGribGrid; FirstNodeToSendBack->prevGribGrid = NULL; (void)sprintf(gribdbg,"FinalNodeToSendBack: %x Last??? %d ", FinalNodeToSendBack,FinalNodeToSendBack->LastStructure); M0sxtrce(gribdbg); } else { /* add the stack starting at TopNewNodeToSendBack ** to the stack ending at FinalNodeToSendBack*/ FinalNodeToSendBack->LastStructure = 1; LastNodeToSendBack->LastStructure = 1; FinalNodeToSendBack->nextGribGrid = TopNewNodeToSendBack; TopNewNodeToSendBack->prevGribGrid = FinalNodeToSendBack; FinalNodeToSendBack = LastNodeToSendBack; Dummy = LastNodeToSendBack->prevGribGrid; (void)sprintf(gribdbg, "FinalNodeToSendBack %x Last? %d %d %d %x %x %x %d", FinalNodeToSendBack,FinalNodeToSendBack->LastStructure, TopNewNodeToSendBack->LastStructure, LastNodeToSendBack->LastStructure,LastNodeToSendBack, TopNewNodeToSendBack,Dummy,Dummy->LastStructure); M0sxtrce(gribdbg); } NumberCompleteStackEntries++; } else { /* if not stitchable, just add it to the Stack */ char dumchar[5]; memcpy((void *)&dumchar[0],(void *)&ThisGribGrid->MCGRIDHEADER[6],(size_t)4); dumchar[4] = (char)0; (void)sprintf(gribdbg,"Put a non-stitchable grid [%d] Level [%d] Par [%s] FHOUR [%d]", ThisGribGrid->MCGRIDHEADER[48], ThisGribGrid->MCGRIDHEADER[9], dumchar,ThisGribGrid->MCGRIDHEADER[5]); M0sxtrce(gribdbg); ThisGribGrid->LastStructure = 1; ThisGribGrid->UsedInSearch = 1; /* put 1 flags in so subsequent ** searches know this grib need not be ** stitched together with others */ if (FirstNodeToSendBack == NULL) { FirstNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); FinalNodeToSendBack = (GribGrid_Header *)malloc( sizeof(GribGrid_Header)); if (FirstNodeToSendBack == NULL || FinalNodeToSendBack == NULL) return(-2); memcpy ( (void *)FirstNodeToSendBack,(void *)ThisGribGrid, sizeof(GribGrid_Header)); FirstNodeToSendBack->prevGribGrid = NULL; FirstNodeToSendBack->nextGribGrid = NULL; FinalNodeToSendBack = FirstNodeToSendBack; } else { NewNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); if (NewNodeToSendBack == NULL ) return(-2); memcpy ( (void *)NewNodeToSendBack,(void *)ThisGribGrid, sizeof(GribGrid_Header)); FinalNodeToSendBack->nextGribGrid = NewNodeToSendBack; NewNodeToSendBack->prevGribGrid = FinalNodeToSendBack; FinalNodeToSendBack = NewNodeToSendBack; FinalNodeToSendBack->nextGribGrid = NULL; } NumberCompleteStackEntries++; } } else { if (ThisGribGrid->UsedInSearch == 0) { if (FirstNodeToSendBack == NULL) { FirstNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); FinalNodeToSendBack = (GribGrid_Header *)malloc( sizeof(GribGrid_Header)); (void)sprintf(gribdbg,"FirstNode was null, now %x", FirstNodeToSendBack); M0sxtrce(gribdbg); if (FirstNodeToSendBack == NULL || FinalNodeToSendBack == NULL) return(-2); memcpy ( (void *)FirstNodeToSendBack,(void *)ThisGribGrid, sizeof(GribGrid_Header)); FirstNodeToSendBack->prevGribGrid = NULL; FirstNodeToSendBack->nextGribGrid = NULL; FinalNodeToSendBack = FirstNodeToSendBack; FinalNodeToSendBack->LastStructure = 1; } else { NewNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); if (NewNodeToSendBack == NULL ) return(-2); ThisGribGrid->LastStructure = 1; memcpy ( (void *)NewNodeToSendBack,(void *)ThisGribGrid, sizeof(GribGrid_Header)); FinalNodeToSendBack->nextGribGrid = NewNodeToSendBack; NewNodeToSendBack->prevGribGrid = FinalNodeToSendBack; FinalNodeToSendBack = NewNodeToSendBack; FinalNodeToSendBack->nextGribGrid = NULL; } NumberCompleteStackEntries++; } } ThisGribGrid = ThisGribGrid->nextGribGrid; StructSearch++; if (NumberCompleteStackEntries >= ngrids_to_get) break; } if (FirstNodeToSendBack != NULL) { *ValidGribFiles = FirstNodeToSendBack; } ThisGribGrid = FirstNodeToSendBack; while (ThisGribGrid != NULL) { (void)sprintf(gribdbg,"Reordered grib value %d %d %d %d %d %d address %x %x %d %d %s", ThisGribGrid->MCGRIDHEADER[48],ThisGribGrid->MCGRIDHEADER[49], ThisGribGrid->MCGRIDHEADER[50],ThisGribGrid->MCGRIDHEADER[51],ThisGribGrid->MCGRIDHEADER[5], ThisGribGrid->MCGRIDHEADER[9],ThisGribGrid,ThisGribGrid->nextGribGrid, ThisGribGrid->UsedInSearch,ThisGribGrid->LastStructure, ThisGribGrid->GRIBFileName); M0sxtrce(gribdbg); ThisGribGrid = ThisGribGrid->nextGribGrid; } return(0); } /* *$ Name: *$ M0IsStitchable -- see if grib geographic number that can *$ be stitched together is present *$ *$ Interface: *$ int M0IsStitchable(int GeoGribNumber) *$ *$ Input: *$ GeoGribNumber - slot 48 from the grid header *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - This is not a stitchable grid *$ 1 - This is a stitchable grid *$ *$ Remarks: *$ Check to see if grid header value in slot 48 is between *$ 37 and 44, 21 and 24, 61 and 64, or 25/26. Those are the *$ stitchable gribs. *$ *$ Categories: *$ grid */ int M0IsStitchable(int GeoGribNumber) { int rc; rc = 0; if ( ( GeoGribNumber >= 37 && GeoGribNumber <= 44 ) || ( GeoGribNumber >= 21 && GeoGribNumber <= 24 ) || ( GeoGribNumber >= 25 && GeoGribNumber <= 26 ) || ( GeoGribNumber >= 61 && GeoGribNumber <= 64 ) ) rc = 1; return(rc); } /* *$ Name: *$ M0IsECMFStitchable -- see if ECMWF grib geographic number that can *$ be stitched together is present *$ *$ Interface: *$ int M0IsECMFStitchable(int GribSource, int GeoGribNumber) *$ *$ Input: *$ GribSource - slot 32 from grid header ("ECMF" is ECMWF grid) *$ GeoGribNumber - slot 48 from the grid header *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - This is not a stitchable grid *$ 1 - This is a stitchable grid *$ *$ Remarks: *$ Check to see if grid header value in slot 48 is 1-4 or 9-12 *$ if slot 32 is ECMW. Such ECMWF grids are stitchable *$ *$ Categories: *$ grid */ int M0IsECMFStitchable(int source, int GeoGribNumber) { int rc; char CSource[5]; memset((void *)&CSource[0],0,(size_t)5); memcpy((void *)&CSource[0],&source,(size_t)4); (void)sprintf(gribdbg,"Source is >%s<",CSource); M0sxtrce(gribdbg); CSource[4] = 0; rc = 0; if (strcmp(CSource,"ECMF") == 0) { if ( ( GeoGribNumber >= 1 && GeoGribNumber <= 4 ) || ( GeoGribNumber >= 9 && GeoGribNumber <= 12 ) ) rc = 1; if ( (GeoGribNumber >=5 && GeoGribNumber <= 8) ) rc = 1; } return(rc); } /* *$ Name: *$ M0NodeComplete -- does the built node contain all the gribs *$ to make a complete grid? *$ *$ Interface: *$ int M0NodeComplete(GribGrid_Header * TopNode) *$ *$ Input: *$ TopNode - the start of a stack of GribGrid_Header structures *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ -1 - Not a stitchable grid, or other failure *$ 0 - This node is not complete *$ 1 - This node is complete *$ *$ Remarks: *$ Check to see if the stack of GribGrid_Header structures contains *$ all the information needed to create a complete grid. *$ *$ Categories: *$ grid */ int M0NodeComplete(GribGrid_Header * Top) { int FirstGrib; int NumEntries = -1; int NumHeaders = 0; GribGrid_Header * Test = NULL; GribGrid_Header * TopTest; char CSource[5]; M0sxtrce("Inside"); memcpy((void *)&CSource[0],(void *)&Top->MCGRIDHEADER[32],(size_t)4); CSource[4] = 0; M0sxtrce(CSource); M0sxtrce("FirstGrib"); FirstGrib = Top->MCGRIDHEADER[48]; Test = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (Test == NULL) return(-1); memcpy( (void *)Test, (void *)Top, sizeof(GribGrid_Header)); TopTest = Test; (void)sprintf(gribdbg,"Node Complete: Firstgrib is %d ",FirstGrib); M0sxtrce(gribdbg); if (FirstGrib >= 1 && FirstGrib <= 12 && strcmp(CSource,"ECMF")==0) NumEntries = 8; if (FirstGrib >= 37 && FirstGrib <= 44) NumEntries = 8; if (FirstGrib >= 21 && FirstGrib <= 24) NumEntries = 4; if (FirstGrib >= 25 && FirstGrib <= 26) NumEntries = 2; if (FirstGrib >= 61 && FirstGrib <= 64) NumEntries = 4; if (NumEntries < 0) return(-1); while (Test != NULL) { NumHeaders++; (void)sprintf(gribdbg,"Grib Number: %d, NumHeaders: %d %d %s \n", Test->MCGRIDHEADER[48],NumHeaders,Test->MCGRIDHEADER[32],CSource); M0sxtrce(gribdbg); Test = Test->nextGribGrid; } free(TopTest); if (NumHeaders == NumEntries) return(1); return(0); } /* *$ Name: *$ M0DiffGeoGrib -- does the present stitchable structure differ from *$ the structures in the stack? *$ *$ Interface: *$ int M0DiffGeoGrib(GribGrid_Header * ThisGribGridHeader, *$ GribGrid_Header * GribGridHeaderStack) *$ *$ Input: *$ ThisGribGridHeader - GribGridHeader that you're testing *$ GribGridHeaderStack - Stack of GribGridHeaders for a stitchable grid *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - This structure does not differ from all structure on the stack *$ 1 - This structure does differ from all structures on the stack *$ *$ Remarks: *$ Does ThisGribGridStructure differ in geo. grib number from the other *$ GribGridStructures in the GribGridHeaderStack? It needs to be added *$ to the stack if that is the case *$ *$ Categories: *$ grid */ int M0DiffGeoGrib(GribGrid_Header * ThisGribGridHeader, GribGrid_Header * GribGridHeaderStack ) { GribGrid_Header * TestGribGridHeader; GribGrid_Header * TopTestGribGridHeader; int match; int FoundOneToSendBack; int * GHead1; int * GHead2; TestGribGridHeader = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); GHead1 = (int *)malloc(sizeof(int)*64); GHead2 = (int *)malloc(sizeof(int)*64); if (TestGribGridHeader == NULL || GHead1 == NULL || GHead2 == NULL)return(-1); TopTestGribGridHeader = TestGribGridHeader; memcpy( (void *)TestGribGridHeader,(void *)GribGridHeaderStack, sizeof(GribGrid_Header)); match = 0; FoundOneToSendBack = 0; while (TestGribGridHeader != NULL) { memcpy((void *)GHead1,(void *)&ThisGribGridHeader->MCGRIDHEADER[0],(size_t)256); memcpy((void *)GHead2,(void *)&TestGribGridHeader->MCGRIDHEADER[0],(size_t)256); (void)sprintf(gribdbg,"Grid 1 par %d grib %d Grid 2 par %d grib %d ", GHead1[6],GHead1[48],GHead2[6],GHead2[48]); M0sxtrce(gribdbg); if (M0CompareGridHead(GHead1,GHead2,TestGribGridHeader->GribType) == 1) { (void)sprintf(gribdbg,"M0CompareGridHead found a match %d vs %d ", ThisGribGridHeader->MCGRIDHEADER[48], TestGribGridHeader->MCGRIDHEADER[48]); M0sxtrce(gribdbg); match = 1; } /* Found a matching grid -- make sure the GRIB numbers are ** DIFFERENT (CompareGridHead ignores slot 48) */ if (match == 1) { if (ThisGribGridHeader->MCGRIDHEADER[48] != TestGribGridHeader->MCGRIDHEADER[48]) { FoundOneToSendBack = 1; } if (FoundOneToSendBack==1) { (void)sprintf(gribdbg,"Found %d a matching grid, GRIB values %d %d", FoundOneToSendBack,TestGribGridHeader->MCGRIDHEADER[48], ThisGribGridHeader->MCGRIDHEADER[48]); M0sxtrce(gribdbg); free(GHead1); free(GHead2); free(TopTestGribGridHeader); if (FoundOneToSendBack == 1) return(FoundOneToSendBack); } } match = 0; TestGribGridHeader = TestGribGridHeader->nextGribGrid; } free(TopTestGribGridHeader); free(GHead1); free(GHead2); return(FoundOneToSendBack); } /* *$ Name: *$ M0FindDeriveMatchGridHeader - find the 1st part of a derived *$ grid stack in the GribGrid_Header stack *$ *$ Interface: *$ #include "mcidas.h" *$ *$ int *$ M0FindDeriveMatchGridHeader(GribGrid_Header ** StructIndex, *$ int * Last, int i, *$ GridDerive * GD, int ** McHeader, int *Index) *$ *$ Input: *$ StructIndex - Array of GribGrid_Header addresses *$ Last - last of a series of stitchables? *$ i - start at this point *$ GD - 1 Grid Derive structure *$ *$ Input and Output: *$ none *$ *$ Output: *$ McHeader - McIDAS grid header of grid that matches *$ Index - StructIndex array member where McHeader is stored *$ *$ Return values: *$ 0 - success *$ -1 - no match on stack *$ -10 - malloc failure *$ *$ Remarks: *$ Given the parameters in the grid derive structure, search the *$ stack of GribGrid_Header structures until a match is found. *$ Return the grid header corresponding to that grid, and adjust *$ the address of the GribGrid_Header stack. *$ *$ Categories: *$ grid */ int M0FindDeriveMatchGridHeader(GribGrid_Header ** StructIndex, int * Last , int i, GridDerive * GD, int ** GridHeader, int * Index) { /* This just returns the header, not the data...it is used to ** count the number of bytes sent back */ int ok; int * GridH; int IndexFound; int StartI; GribGrid_Header * ThisGribGrid = NULL; GridDerive * ThisGD = NULL; GridDerive * StackGD = NULL; GridH = (int *)malloc(sizeof(int)*64); ThisGD = (GridDerive *)malloc(sizeof(GridDerive)); StackGD = (GridDerive *)malloc(sizeof(GridDerive)); ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if ( ThisGribGrid == NULL || StackGD == NULL || GridH == NULL || ThisGD == NULL) return(-10); memcpy((void *)ThisGD,(void *)GD,sizeof(GridDerive)); (void)sprintf(gribdbg,"Start! M0FindDeriveMatchGridHeader Look for %s, i is %d %p", ThisGD->parm,i,StructIndex[i]); M0sxtrce(gribdbg); StartI = -999; while (StructIndex[i] != (GribGrid_Header *)NULL) { (void)sprintf(gribdbg,"i is %d %p, Last is %d ",i,StructIndex[i],Last[i]); M0sxtrce(gribdbg); if (StartI == -999) StartI = i; if (Last[i] == 1) { memcpy( (void *)ThisGribGrid,(void *)StructIndex[i], sizeof(GribGrid_Header)); ok = M0CompareGribGrid_Derive(ThisGribGrid,ThisGD); if (ok == 1) { /* found a match on 1st component (last stitchable */ /* component) of derived quantities .... */ /* now go through and look for */ /* the other grids */ /* */ (void)sprintf(gribdbg,"Found a parm %s %d %d %d %d i is %d, Last is %d", ThisGD->parm,ThisGribGrid->MCGRIDHEADER[9], ThisGribGrid->MCGRIDHEADER[6], ThisGD->gribgeo,ThisGribGrid->MCGRIDHEADER[48],i,Last[i]); M0sxtrce(gribdbg); ok = M0GribGetGridHeader(ThisGribGrid,(Fint *)GridH); *GridHeader = GridH; (void)sprintf(gribdbg, "Matched, now find all frgrids needed to derive "); M0sxtrce(gribdbg); StackGD = ThisGD->nextDerive; while (StackGD != NULL) { int jj, Match ; jj = 0; Match = 0; while (StructIndex[jj] != (GribGrid_Header *)NULL) { ok = M0MatchNextDerive(StructIndex,StackGD,(int *)GridH,&IndexFound); (void)sprintf(gribdbg,"FOUND a parm %s %d ", StackGD->parm,GridH[6]); M0sxtrce(gribdbg); if (ok == 1) { Match=1; break; } jj++; } if (Match == 0) { /* no match on this particular start ** need to go back and find the 1st one again */ /* reset GridDerive stack to top */ M0sxtrce("Reset and try again"); memcpy((void *)ThisGD,(void *)GD,sizeof(GridDerive)); goto EndOfLoop; } (void)sprintf(gribdbg,"Matched the next part of the GD %x %x ", StackGD,StackGD->nextDerive); M0sxtrce(gribdbg); StackGD = StackGD->nextDerive; } /* if we're here -- we've found a complete set of Derive grids ** return */ M0sxtrce("Found complete set"); (void)sprintf(gribdbg,"Found complete set!! i is %d StartI is %d ", i,StartI); M0sxtrce(gribdbg); *Index = StartI; return(0); } else { M0sxtrce("....Compare GribGridDerive failed ...goto next grid"); return(-1); } EndOfLoop: ; StartI = -999; } else { (void)sprintf(gribdbg,".....skipping a non-last grid at slot %d",i); M0sxtrce(gribdbg); } i++; } M0sxtrce("Did not find a complete set!"); return(-1); } /* *$ Name: *$ M0CompareGribGrid_Derive - compare grid header in GribGrid_Header *$ structure to a GridDerive request: are they compatible? *$ *$ Interface: *$ #include "mcidas.h" *$ *$ int *$ M0CompareGribGrid_Derive(GribGrid_Header * Search, GridDerive * GD) *$ *$ Input: *$ Search - a single GribGrid_Header structure *$ GD - 1 Grid Derive structure *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 1 - match *$ 0 - no match *$ *$ Remarks: *$ *$ *$ Categories: *$ grid */ int M0CompareGribGrid_Derive(GribGrid_Header *Search , GridDerive *GD) { int i,ok; int FoundEnd; char Param[5]; char Level[5]; char Src[5]; char Proj[5]; int match = 1; /* assume all matches */ if ( (GD->day != -1 ) && (GD->day%100000 != Search->MCGRIDHEADER[3]%100000)) { (void)sprintf(gribdbg,"Failed in day check %d %d %d %d ", GD->day,Search->MCGRIDHEADER[3], GD->day%100000,Search->MCGRIDHEADER[3]%100000); M0sxtrce(gribdbg); return(0); } if ( (GD->time != -1 ) && GD->time != Search->MCGRIDHEADER[4]) { (void)sprintf(gribdbg,"Failed in time check %d %d ", GD->time,Search->MCGRIDHEADER[4]); M0sxtrce(gribdbg); return(0); } if ( (GD->fhour != -1 ) && GD->fhour != Search->MCGRIDHEADER[5]) { (void)sprintf(gribdbg,"Failed in vtime check %d %d ", GD->fhour,Search->MCGRIDHEADER[5]); M0sxtrce(gribdbg); return(0); } if ( (GD->gribgeo != -1) && GD->gribgeo != Search->MCGRIDHEADER[48]) { if ( ( GD->gribgeo == 5678 && (Search->MCGRIDHEADER[48] >=5 && Search->MCGRIDHEADER[48] <= 8)) || ( GD->gribgeo == 2124 && (Search->MCGRIDHEADER[48] >=21&& Search->MCGRIDHEADER[48] <=24)) || ( GD->gribgeo == 2526 && (Search->MCGRIDHEADER[48] ==25|| Search->MCGRIDHEADER[48] ==26)) || ( GD->gribgeo == 6164 && (Search->MCGRIDHEADER[48] >=61&& Search->MCGRIDHEADER[48] <=64)) || ( GD->gribgeo == 3744 && (Search->MCGRIDHEADER[48] >=37&& Search->MCGRIDHEADER[48] <=44)) || ( GD->gribgeo == 14912 && (Search->MCGRIDHEADER[48] >= 1 && Search->MCGRIDHEADER[48] <=12 && (Search->MCGRIDHEADER[48] > 8 || Search->MCGRIDHEADER[48] < 5)))) { M0sxtrce("Didn't Fail after all"); match = 1; } if (match == 0) { (void)sprintf(gribdbg,"Failed in gribgeo check %d %d ", GD->gribgeo,Search->MCGRIDHEADER[48]); M0sxtrce(gribdbg); return(0); } } if ( (GD->gribmdl != -1) && GD->gribmdl != Search->MCGRIDHEADER[50]) { (void)sprintf(gribdbg,"Failed in gribmdl check %d %d ", GD->gribmdl,Search->MCGRIDHEADER[50]); M0sxtrce(gribdbg); return(0); } if ( (GD->griblev != -1) && GD->griblev != Search->MCGRIDHEADER[51]) { (void)sprintf(gribdbg,"Failed in griblev check %d %d ", GD->griblev,Search->MCGRIDHEADER[51]); M0sxtrce(gribdbg); return(0); } if ( (GD->gribpar != -1) && GD->gribpar != Search->MCGRIDHEADER[49]) { (void)sprintf(gribdbg,"Failed in gribpar check %d %d ", GD->gribpar,Search->MCGRIDHEADER[49]); M0sxtrce(gribdbg); return(0); } /* if we're here, all the matches above worked...check the strings now */ memcpy( (void *)&Param[0],(void *)&Search->MCGRIDHEADER[6],(size_t)4); Param[4] = (char)0; memcpy( (void *)&Src[0],(void *)&Search->MCGRIDHEADER[32],(size_t)4); Src[4] = (char)0; switch (Search->MCGRIDHEADER[33]) { case 1: case 4: (void)sprintf(&Proj[0],"MERC"); Proj[4] = (char)0; break; case 6: case 2: (void)sprintf(&Proj[0],"CONF"); break; default: break; } /* convert integer level in grid header to a string */ ok = m0levchr_((Fint *)&Search->MCGRIDHEADER[9],(char *)&Level[0],4); Level[4] = (char)0; /* strip off trailing blanks in Level */ FoundEnd = 1; for (i = 4; i >= 0; i--) { if (FoundEnd == 0) break; if (Level[i] == (char)0) FoundEnd = 1; if (FoundEnd == 1) { if (Level[i] == (char)32 || Level[i] == (char)0) { Level[i] = (char)0; FoundEnd = 1; } else FoundEnd = 0; } } /* strip off trailing blanks in Param */ FoundEnd = 1; for (i = 4; i >= 0; i--) { if (FoundEnd == 0) break; if (Param[i] == (char)0) FoundEnd = 1; if (FoundEnd == 1) { if (Param[i] == (char)32 || Param[i] == (char)0) { Param[i] = (char)0; FoundEnd = 1; } else FoundEnd = 0; } } /* strip off trailing blanks in Proj */ FoundEnd = 1; for (i = 4; i >= 0; i--) { if (FoundEnd == 0) break; if (Proj[i] == (char)0) FoundEnd = 1; if (FoundEnd == 1) { if (Proj[i] == (char)32 || Proj[i] == (char)0) { Proj[i] = (char)0; FoundEnd = 1; } else FoundEnd = 0; } } /* strip off trailing blanks in Src */ FoundEnd = 1; for (i = 4; i >= 0; i--) { if (FoundEnd == 0) break; if (Src[i] == (char)0) FoundEnd = 1; if (FoundEnd == 1) { if (Src[i] == (char)32 || Src[i] == (char)0) { Src[i] = (char)0; FoundEnd = 1; } else FoundEnd = 0; } } if ( (GD->parm != NULL && strcmp(GD->parm," ") != 0 && strcmp(GD->parm,"")!= 0) && strcmp(GD->parm,Param) != 0 ) { (void)sprintf(gribdbg,"CompareGribGridDerive Match failed in param >%s< >%s< ",GD->parm,Param); M0sxtrce(gribdbg); return(0); } if ( (GD->level != NULL && strcmp(GD->level," ") != 0 && strcmp(GD->level,"") != 0) && strcmp(GD->level,Level) != 0 ) { (void)sprintf(gribdbg,"Match failed in level %s %s ",GD->level,Level); M0sxtrce(gribdbg); return(0); } if ( (GD->src != NULL && strcmp(GD->src," ") != 0 && strcmp(GD->src,"") != 0) && strcmp(GD->src,Src) != 0 ) { (void)sprintf(gribdbg,"Match failed in SRC >%s< >%s< ",GD->src,Src); M0sxtrce(gribdbg); return(0); } if ( (GD->proj != NULL && strcmp(GD->proj," ") != 0 && strcmp(GD->proj,"") != 0) && strcmp(GD->proj,Proj) != 0 ) { if (strcmp(GD->proj,"PS") == 0 && strcmp(Proj,"CONF") == 0 ) goto End; if (strcmp(GD->proj,"LAMB") == 0 && strcmp(Proj,"CONF") == 0 ) goto End; (void)sprintf(gribdbg,"Match failed in proj >%s< >%s< ",GD->proj,Proj); M0sxtrce(gribdbg); return(0); } End: ; return(1); } /* *$ Name: *$ M0MatchNextDerive - Find the GribGrid_Header that matches the *$ Derive structure and the grid header *$ *$ Interface: *$ #include "mcidas.h" *$ *$ int *$ M0MatchNextDerive(GribGrid_Header ** StructIndex, GridDerive * GD, *$ int * GridHeader, int * IndexFound ) *$ *$ Input: *$ StructIndex- List of addresses of GribGrid_Headers *$ GD - 1 Grid Derive structure *$ GridHeader - Grid Header that matched earlier GridDerive *$ *$ Input and Output: *$ none *$ *$ Output: *$ IndexFound - index in StructIndex of match *$ *$ Return values: *$ 1 - match *$ 0 - no match *$ *$ Remarks: *$ Find the GribGrid_Header structure that matches all the search criteria *$ in the GridDerive structure. In addition, the grid found must *$ match the values in the GridHeader -- except those specified in *$ the GridDerive structure. *$ *$ *$ Categories: *$ grid */ int M0MatchNextDerive (GribGrid_Header ** StructIndex, GridDerive * GD, int * GridHeader, int * IndexFound) { /* this function just verifies that the grid exists in the stack... ** nothing else is needed to send back */ int ok,i,j; int Fail; GribGrid_Header * Start = NULL; Fint * TestGridHeader = NULL; Start = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); if (Start == NULL) return(-1); TestGridHeader = (Fint *)malloc(sizeof(Fint)*64); if (TestGridHeader == NULL) return(-1); Fail = 1; i = 0; while (StructIndex[i] != (GribGrid_Header *)NULL) { if (Fail == 0) return(1); memcpy( (void *)Start, (void *)StructIndex[i], sizeof(GribGrid_Header)); ok = M0CompareGribGrid_Derive(Start,GD); if (ok == 1) { /* now compare the GridHeader found ** to the one found previously */ Fail = 0; ok = M0GribGetGridHeader(Start,TestGridHeader); *IndexFound = i; M0sxtrce("Compare the grid that matches GD to previous Grid"); for (j = 0; j < 2 ; j++) { /* check sizes */ if (TestGridHeader[j] != GridHeader[j]) { (void)sprintf(gribdbg,"Failed on %d size: %d %d ",j,GridHeader[j], TestGridHeader[j]); M0sxtrce(gribdbg); Fail = 1; goto Note; } } if (GD->day == -1 && (TestGridHeader[3]%100000 != GridHeader[3]%100000) ) { (void)sprintf(gribdbg,"Failed on day %d %d ",GridHeader[3], TestGridHeader[3]); /* M0sxtrce(gribdbg); */ Fail = 1; goto Note; } if (GD->time == -1 && (TestGridHeader[4] != GridHeader[4]) ) { (void)sprintf(gribdbg,"Failed on time %d %d ",GridHeader[4], TestGridHeader[4]); /* M0sxtrce(gribdbg); */ Fail = 1; goto Note; } if (GD->fhour == -1 && (TestGridHeader[5] != GridHeader[5]) ) { (void)sprintf(gribdbg,"Failed on fhour %d %d ",GridHeader[5], TestGridHeader[5]); M0sxtrce(gribdbg); Fail = 1; goto Note; } /* if (GD->gribgeo == -1 && This check is handled in points 33-39 and removing it allows stitchable grids that have different grib numbers to match (TestGridHeader[48] != GridHeader[48]) ) { (void)sprintf(gribdbg,"Failed on gribgeo %d %d %d ",GridHeader[48], TestGridHeader[48]); M0sxtrce(gribdbg); Fail = 1; goto Note; } */ /* if (GD->gribmdl == -1 && (TestGridHeader[50] != GridHeader[50]) ) { (void)sprintf(gribdbg,"Failed on slot 50 %d %d ",GridHeader[50], TestGridHeader[50]); M0sxtrce(gribdbg); Fail = 1; goto Note; } */ if ( (strlen(GD->level) == 0 || strcmp(GD->level," ") == 0) && (TestGridHeader[9] != GridHeader[9]) ) { (void)sprintf(gribdbg,"Failed on level %d %d ",GridHeader[9], TestGridHeader[9]); M0sxtrce(gribdbg); Fail = 1; goto Note; } if ((strlen(GD->src) == 0 || strcmp(GD->src," ") == 0) && (TestGridHeader[32] != GridHeader[32]) ) { (void)sprintf(gribdbg,"Failed on src %d %d ",GridHeader[32], TestGridHeader[32]); M0sxtrce(gribdbg); Fail = 1; goto Note; } for (i = 33; i < 39 ; i++) { /* derived grids have to be on the ** same projection plane */ if (TestGridHeader[i] != GridHeader[i]) { if ( (i == 34 || i == 35) && /* 34 and 35 can be 'close enough' */ (GridHeader[33] == 2 || GridHeader[33] == 6) ) { float Value1 = GridHeader[i]/10000.; float Value2 = TestGridHeader[i]/10000.; float pct = (fabs((Value1-Value2)/Value1))*100.; if (pct > 1.) { Fail = 1; } else { M0sxtrce("Values are close enough"); } } else { (void)sprintf(gribdbg,"Failed on projection %d %d %d ",i, GridHeader[i],TestGridHeader[i]); M0sxtrce(gribdbg); Fail = 1; goto Note; } } } if (Fail == 0) { (void)sprintf(gribdbg,"Hey Hey Hey!! A Complete Match!"); M0sxtrce(gribdbg); free(TestGridHeader); free(Start); return(1); break; } } Note: i++; } free(Start); return(0); } /* *$ Name: *$ M0GetFirstDerive - Get the first data/header of a series of *$ grids being used ultimately to derive on the client *$ *$ Interface: *$ #include "mcidas.h" *$ *$ int *$ M0GetFirstDerive(GribGrid_Header ** StructIndex, int *LastInStitch, *$ int * index, *$ GridDerive * GD, int ** GridData, int ** GridHeader) *$ *$ Input: *$ StructIndex - array of structure addresses *$ LastInStitch- is this a stitchable grid? *$ index - index of structure *$ GD - 1 Grid Derive structure *$ *$ Input and Output: *$ none *$ *$ Output: *$ GridData - decoded grid data *$ GridHeader - decoded grid data *$ *$ Return values: *$ 0 - success *$ -5 - malloc failure *$ *$ Remarks: *$ Find and returns the first grid header/grid data for a series of *$ grids used to derive a quantity on the client. Note that if the *$ grid is stitchable, a stitched grid is returned. If a grid is *$ returned, then the other constituent grids also exist. *$ *$ *$ Categories: *$ grid */ int M0GetFirstDerive(GribGrid_Header ** StructIndex, int * LastInStitch, int * INDEX, GridDerive * GD, Fint ** GridData, Fint ** GridHeader) { int i,ok,Index; Fint * McHeader = NULL; Fint * McData = NULL; McHeader = (Fint *)malloc(sizeof(int)*64); if (McHeader == NULL) return(-5); /* find the GribGrid_Header structure that point to the first ** grid of a complete series of constituent grids for a derivable ** quantity */ i = *INDEX; (void)sprintf(gribdbg,">>>M0GetFirstDerive is i is %d , look for >%s< ",i, GD->parm); M0sxtrce(gribdbg); ok = M0FindDeriveMatchGridHeader(StructIndex,LastInStitch,i,GD,&McHeader,&Index); (void)sprintf(gribdbg, "M0FindDeriveMatchGridHeader ok returned as %d %d Index is %d %d %d", ok,McHeader[9],Index,GD->gribgeo,McHeader[48]); M0sxtrce(gribdbg); if (ok < 0) return(-1); if (GD->gribgeo != -1) McHeader[48] = GD->gribgeo; i = Index; McData = (Fint *)malloc(sizeof(int)*McHeader[0]); if (McData == NULL) return(-5); if (GRIBSaveGridData == 1) { ok = M0GribGetGridData(&StructIndex[Index],&LastInStitch[Index], McData,McHeader); (void)sprintf(gribdbg,"Saved gridheader %d %d %d",McHeader[9],McData[0], McHeader[48]); M0sxtrce(gribdbg); if (ok == 0) i = Index; *GridData = McData; } /* Reset i....go through LastInStitch... */ while (LastInStitch[i] == 0) i++; *INDEX = i; *GridHeader = McHeader; return(0); } /* *$ Name: *$ M0GetMatchDerive - Get the nth data/header of a series of *$ grids being used ultimately to derive on the client *$ *$ Interface: *$ #include "mcidas.h" *$ *$ int *$ M0GetMatchDerive(GridDerive *GD, GribGrid_Header ** AddyIndex, *% int * LastinStitch, *$ int * MatchHead, int ** GridData, int ** GridHeader) *$ *$ Input: *$ GD - 1 Grid Derive structure *$ AddyIndex - Addresses of structures *$ LastInStitch - the last of a series of stitchable grids? *$ MatchHead - grid header of 1st Grid in derive structure *$ *$ Input and Output: *$ none *$ *$ Output: *$ MatchGridData - decoded grid data *$ MatchGridHeader - decoded grid data *$ *$ Return values: *$ 0 - success *$ -1 - Failed to find matching grid *$ -5 - malloc failure *$ -10 - failed to get grid data *$ *$ Remarks: *$ Gets the grid in a series of grids for deriving that matches the *$ criteria in GridDerive and also the values in a grid header *$ previously found. *$ Error code -1 should not occur. *$ *$ *$ Categories: *$ grid */ int M0GetMatchDerive(GridDerive * GD, GribGrid_Header ** AddressIndex, int * LastInStitch, Fint * MatchHead, Fint ** GridData, Fint ** GridHeader) { int i,ok; Fint * McHeader = NULL; Fint * McData = NULL; /* GribGrid_Header * ThisGribGrid; char temp[4096];*/ int IndexFound; McHeader = (Fint *)malloc(sizeof(int)*64); if (McHeader == NULL ) return(-5); i = 0; /* Is the matching grid here? */ M0sxtrce(GD->parm); ok = M0MatchNextDerive(&AddressIndex[i],GD,MatchHead,&IndexFound); if (ok == 1) { /* found a match! */ (void)sprintf(gribdbg, "M0MatchNextDerive found a match -- %d Last? %d at index %d ", i,LastInStitch[i],IndexFound); M0sxtrce(gribdbg); McData = (Fint *)malloc(sizeof(int)*MatchHead[0]); if (McData == NULL) return(-5); ok = M0GribGetGridData( &AddressIndex[IndexFound], &LastInStitch[IndexFound], (Fint *)McData,(Fint *)McHeader); if (ok != 0) return(-10); (void)sprintf(gribdbg,"Match Header is %d %d ",McHeader[9],McHeader[48]); M0sxtrce(gribdbg); *GridData = McData; *GridHeader = McHeader; return(0); } return(-1); } void GRIBSaveGridDataYes(void) { GRIBSaveGridData = 1; } void GRIBSaveGridDataNo(void) { GRIBSaveGridData = 0; } /* *$ Name: *$ M0MakeStructIndex - Pair up matching GribGrid structures *$ in the linked list and make an index *$ *$ Interface: *$ int M0MakeStructIndex( GribGrid_Header * ValidGribFiles, *$ GridRequestObj * Request, int GDpresent, int ngrids_to_get, *$ GribGrid_Header *** StructPtr, *$ int ** LastInFile ) *$ *$ Input: *$ ValidGribFiles - the un-ordered set of GribFiles *$ ngrids_to_get - number of grids requested of the server *$ Request - Grid Request Object *$ GDpresent - Grid Derive object is present (1 or 2) or not (0) *$ *$ Input and Output: *$ none *$ *$ Output: *$ StructPtr - integer array containing pointers to sorted list *$ LastInFile - integer array telling whether structure pointed to *$ is the last one for a stitchable *$ *$ Return values: *$ 0 - success *$ -1 - file does not contain GRIB data *$ -2 - malloc failure *$ -10 - file software errors (fopen or fstat) *$ -12 - Failure in M0GribMakeGridHeader *$ *$ Remarks: *$ This function scans through the linked list in the GribGrid_Header *$ structure and puts the files to be combined (for thinned grids) *$ in sequential order *$ Only the first ngrids_to_get'th GribGrid_Header structures are *$ reordered. *$ *$ Categories: *$ grid */ int M0MakeStructIndex(GribGrid_Header * ValidGribFiles, GridRequestObj *Request, int GDpresent, int ngrids_to_get, GribGrid_Header *** StrctPtr, int ** LastStrct ) { GribGrid_Header * ThisGribGrid = NULL; GribGrid_Header * TopNode = NULL; GribGrid_Header * TopNewNodeToSendBack = NULL; GribGrid_Header * NewNodeToSendBack = NULL; GribGrid_Header * LastNodeToSendBack = NULL; GribGrid_Header * Searching = NULL; int i; int StructSearch = 0; int StructCnt = 0; int GribRequested; int TopGridHeader[64]; int NumberCompleteStackEntries = 0; int GribCnt = 1; /* int SanityCheck = 0;*/ GribGrid_Header ** StructPtr; int *LastInFile; int AtTop=1; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); TopNode = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); Searching = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); StructPtr = (GribGrid_Header **)malloc(sizeof(GribGrid_Header *)*100000); LastInFile = (int *)malloc(sizeof(int)*100000); if (ThisGribGrid == NULL || TopNode == NULL || Searching == NULL || StructPtr == NULL || LastInFile == NULL) return(-2); if (ValidGribFiles == NULL) return(0); memcpy( (void *)TopNode, (void *) ValidGribFiles,sizeof(GribGrid_Header)); GribRequested = 0; GribRequested = IsGribRequested(Request,GDpresent,0); (void)sprintf(gribdbg,"MAKESTRUCTINDEX GribRequested is %d %d \n",GribRequested,GDpresent); M0sxtrce(gribdbg); /* if (Request->grid_ngrid > 0) GribRequested = 1; */ memcpy( (void *)ThisGribGrid, (void *) TopNode,sizeof(GribGrid_Header)); /* Now, walk through all the found files....We want to put all the matching ** grib files next to each other on the list. That way, the stitching ** can be easily done, and/or the grids that are needed for deriving ** on the client can be sent sequentially */ while (ThisGribGrid != NULL) { (void)sprintf(gribdbg, "MakeSTructIndex GRIB : %d ENS: %d GribRequested: %d \n", ThisGribGrid->MCGRIDHEADER[48],ThisGribGrid->MCGRIDHEADER[19], GribRequested); M0sxtrce(gribdbg); if (ThisGribGrid->UsedInSearch == 0 && GribRequested == 0) { if (M0IsStitchable(ThisGribGrid->MCGRIDHEADER[48]) == 1 || M0IsECMFStitchable(ThisGribGrid->MCGRIDHEADER[32],ThisGribGrid->MCGRIDHEADER[48]) == 1) { /* Put onto new stack, and then search for the matching ** structures */ StructPtr[StructCnt] = ThisGribGrid; LastInFile[StructCnt] = 0; StructCnt++; (void)sprintf(gribdbg,"Found a stitchable grid %d ", ThisGribGrid->MCGRIDHEADER[48]); M0sxtrce(gribdbg); memcpy( (void *)&TopGridHeader[0], (void *) &ThisGribGrid->MCGRIDHEADER[0],(size_t)256); ThisGribGrid->UsedInSearch = 1; ThisGribGrid->StitchFlag = 1; if (AtTop == 1) { TopNode->UsedInSearch = 1; TopNode->StitchFlag = 1; } ThisGribGrid->LastStructure = 1; TopNewNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); if (TopNewNodeToSendBack == NULL ) return(-2); /* TopNewNodeTo... always contains the Node being built */ LastNodeToSendBack = (GribGrid_Header *)malloc( sizeof(GribGrid_Header)); if (LastNodeToSendBack == NULL) return(-2); memcpy ( (void *)TopNewNodeToSendBack,(void *)ThisGribGrid, sizeof(GribGrid_Header)); TopNewNodeToSendBack->prevGribGrid = NULL; TopNewNodeToSendBack->nextGribGrid = NULL; LastNodeToSendBack = TopNewNodeToSendBack; /* start at top of stack, now, and go down, looking for ** structures that match the first one, except for the ** geographic grib number **/ Searching = TopNode; AtTop = 1; while (Searching != NULL) { if (Searching->UsedInSearch == 0) { if ( M0DiffGeoGrib(Searching,TopNewNodeToSendBack) == 1 ) { /* we have found a file (ThisGribGrid) that matches ** the values in TopGridHeader, but doesn't already ** reside in the TopNewNodeToSendBack stack */ StructPtr[StructCnt] = Searching; LastInFile[StructCnt] = 0; StructCnt++; (void)sprintf(gribdbg,"Add to NewNodeToSendBack %x %x %x %d ", TopNewNodeToSendBack,LastNodeToSendBack,Searching, Searching->MCGRIDHEADER[48]); M0sxtrce(gribdbg); Searching->UsedInSearch = 1; Searching->StitchFlag = 1; if (AtTop == 1) { TopNode->UsedInSearch = 1; TopNode->StitchFlag = 1; } NewNodeToSendBack = (GribGrid_Header *)malloc (sizeof(GribGrid_Header)); if (NewNodeToSendBack == NULL ) return(-2); memcpy((void *)NewNodeToSendBack,(void *)Searching, sizeof(GribGrid_Header)); NewNodeToSendBack->UsedInSearch = 1; NewNodeToSendBack->StitchFlag = 1; NewNodeToSendBack->LastStructure = 1; LastNodeToSendBack->nextGribGrid = NewNodeToSendBack; LastNodeToSendBack->LastStructure = 0; NewNodeToSendBack->nextGribGrid = NULL; NewNodeToSendBack->prevGribGrid = LastNodeToSendBack; LastNodeToSendBack = NewNodeToSendBack; (void)sprintf(gribdbg," %x Top %x Next %x Last? Top %d Last %d ", NewNodeToSendBack, TopNewNodeToSendBack, TopNewNodeToSendBack->nextGribGrid, TopNewNodeToSendBack->LastStructure, LastNodeToSendBack->LastStructure); M0sxtrce(gribdbg); M0sxtrce("Check for NODE completeness"); if (M0NodeComplete(TopNewNodeToSendBack) == 1) { M0sxtrce("Yippy!! FOund a COMPLETE Node "); goto AddStack; } } else { ; } } Searching = Searching->nextGribGrid; if (AtTop == 1) AtTop = 0; } AddStack: M0sxtrce(" Free up the stack "); i = 0; NumberCompleteStackEntries++; Searching = TopNewNodeToSendBack; while (Searching != NULL) { i++; TopNewNodeToSendBack = Searching->nextGribGrid; free(Searching); Searching = TopNewNodeToSendBack; } LastInFile[StructCnt-1] = 1; } else { /* if not stitchable, just add it to the Stack */ char dumchar[5]; memcpy((void *)&dumchar[0],(void *)&ThisGribGrid->MCGRIDHEADER[6],(size_t)4); dumchar[4] = (char)0; (void)sprintf(gribdbg,"Put a non-stitchable grid [%d] Level [%d] Par [%s] FHOUR [%d] ", ThisGribGrid->MCGRIDHEADER[48], ThisGribGrid->MCGRIDHEADER[9], dumchar,ThisGribGrid->MCGRIDHEADER[5]); M0sxtrce(gribdbg); StructPtr[StructCnt] = ThisGribGrid; LastInFile[StructCnt] = 1; StructCnt++; ThisGribGrid->LastStructure = 1; ThisGribGrid->UsedInSearch = 1; /* put 1 flags in so subsequent ** searches know this grib need not be ** stitched together with others */ NumberCompleteStackEntries++; } } else { if (ThisGribGrid->UsedInSearch == 0) { (void)sprintf(gribdbg,"Requested grib , so add 1 structure %x to stack ",ThisGribGrid); M0sxtrce(gribdbg); StructPtr[StructCnt] = ThisGribGrid; LastInFile[StructCnt] = 1; StructCnt++; NumberCompleteStackEntries++; } } ThisGribGrid = ThisGribGrid->nextGribGrid; if (AtTop == 1) AtTop == 0; GribCnt++; StructSearch++; (void)sprintf(gribdbg,"Number Complete Stack entries: %d , ngrids_to_get: %d ", NumberCompleteStackEntries,ngrids_to_get); M0sxtrce(gribdbg); if (NumberCompleteStackEntries >= ngrids_to_get) break; } StructPtr[StructCnt] = (GribGrid_Header *)NULL; LastInFile[StructCnt] = -999; *StrctPtr = StructPtr; *LastStrct = LastInFile; return(0); } /* *$ Name: *$ M0CountGridHeader -- count grid headers for subsecting *$ *$ Interface: *$ int M0CountGridHeader( GribGrid_Header ** StructIndex, *$ int * Last, GridDerive *GD, *$ int * largest, int ngrids_to_send ,GridRequestObj * Grids_R, *$ int doGridDerive, double brow, double erow, double bcol, *$ double ecol, int llswitch, int incrow, int inccol, int numsub, *$ int dirget) *$ *$ Input: *$ StructIndex - array of structure addresses *$ Last - is structure that last in a series of stitchables? *$ GD - Grid derive Object *$ GR - Grid Request Object showing sort conditions *$ ngrids_to_send - number of grids to send to client *$ doGridDerive - flag saying deriving is being done *$ brow - begin point (in the row) for subsecting *$ erow - end point (in the row) for subsecting *$ bcol - begin column (in the row) for subsecting *$ ecol - end column (in the row) for subsecting *$ incrow - every incrow'th row *$ inccol - every inccol'th col *$ llswitch - 1 for 'ROWCOL'; 0 for 'LATLON' *$ numsub - 0 if no subsecting being done *$ dirget - 1 if sending just directory, 0 if sending grid too *$ *$ Input and Output: *$ none *$ *$ Output: *$ largest - largest number of points in grid in linked list *$ *$ Return values: *$ >0 - number of grid headers in linked list *$ 0 - structure contains no data *$ -10 - trapped an infinite loop? *$ -20 - Out of memory *$ -50 - Subsect failure *$ *$ Remarks: *$ Go through the GribGrid_Header structure and count the *$ number of gridheaders. *$ Note that some of the elements on the stack will be later *$ combined; only count one of the headers in each of these. *$ The gridheaders already reflect the stitched-together size *$ of the grid. *$ In addition, if a Derivation is being done, match up the grids *$ *$ Categories: *$ grid */ int M0CountGridHeader ( GribGrid_Header ** StructAddress, int *Last, GridDerive *GD, int *Largest, int ngrids_to_send, GridRequestObj * GR, int doGridDerive, int * bytes, double brow, double erow, double bcol, double ecol, int incrow, int inccol, int llswitch, int numsub, int dirget ) { int ngrids=0; int TotBytes=0; int test = 0; int cnt = 0; int i,Index; int ok,iret; int * GridHeader; int uGridHeader[HEDSIZ]; int TotDerive; /* number of grids needed to derive*/ GribGrid_Header * ThisGribGrid; GridDerive * ThisGD = NULL; GridDerive * CntGD = NULL; Fint * GridIn; Fint * GridOut; Fint * GridHeadSubSect; double firstrow,lastrow; double firstcol,lastcol; int rowinc,colinc; int llrc; firstrow = brow; lastrow = erow; firstcol = bcol; lastcol = ecol; rowinc = incrow; colinc = inccol; llrc = llswitch; i = 0; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); GridHeader = (int *)malloc(sizeof(int)*64); ThisGD = (GridDerive *)malloc(sizeof(GridDerive)); CntGD = (GridDerive *)malloc(sizeof(GridDerive)); if ( GridHeader == NULL || ThisGribGrid == NULL || ThisGD == NULL || CntGD == NULL ) return(-20); /* simplest case -- no Deriving, no uvflag */ if (doGridDerive == 0 && GR->uvflag == 0 || doGridDerive == 1 && GD->present == 2) { int gbtablereset = 1; (void)sprintf(gribdbg,"Simple case, StructAddy %p ",StructAddress[i]); M0sxtrce(gribdbg); iret = gbtable002( (IS *)NULL,(PDS *)NULL,(GBTAB002 *)NULL,gbtablereset); while ( StructAddress[i] != (GribGrid_Header *)NULL ) { if (Last[i] == 1) { memcpy( (void *)ThisGribGrid,(void *)StructAddress[i], sizeof(GribGrid_Header)); ok = M0GribGetGridHeader(ThisGribGrid,GridHeader); if (GridHeader[0] > test) test = GridHeader[0]; if (numsub > 0) { /* we want to subsect the grid here -- the grid actual values ** at this points are irrelevant... */ GridHeadSubSect = (Fint *)malloc(sizeof(int)*64); GridIn = (Fint *)malloc(sizeof(int)*GridHeader[0]); GridOut= (Fint *)malloc(sizeof(int)*GridHeader[0]); if (GridIn == NULL || GridOut == NULL || GridHeadSubSect == NULL) return(-20); ok = McSubSectGrid(GridHeader,GridIn,GridHeadSubSect,GridOut, &firstrow, &lastrow, rowinc, &firstcol, &lastcol, colinc, llrc); if (ok != 0) return(-50); memcpy( GridHeader,GridHeadSubSect,(size_t)256 ); free(GridIn); free(GridHeadSubSect); free(GridOut); } ngrids++; TotBytes += 4*GridHeader[0]; } i++; cnt++; if (cnt > 1000000) { (void)sprintf(gribdbg,"Infinite loop?"); M0sxtrce(gribdbg); return(-10); } if (ngrids >= ngrids_to_send) goto EndCount; } goto EndCount; } if (GR->uvflag == 1) { /* need paired u-v grids...go through and find 'em */ i = 0; (void)sprintf(gribdbg,"Paired parameters, %d Address: %p",i,StructAddress[i]); M0sxtrce(gribdbg); while (StructAddress[i] != (GribGrid_Header *)NULL) { char tstr[5]; int tint; (void)sprintf(gribdbg, "Paired parameters, %d Address: %p %d",i,StructAddress[i],Last[i]); M0sxtrce(gribdbg); if (Last[i] == 1) { /* only compute sizes for ** the last in a series of ** grids that will be sent back ** after being combined */ memcpy( (void *)ThisGribGrid,(void *)StructAddress[i], sizeof(GribGrid_Header)); tint = ThisGribGrid->MCGRIDHEADER[6]; memcpy(&tstr[0],&tint,sizeof(int)); tstr[4] = 0; (void)sprintf(gribdbg,"size %d lev %d par >%s< ", ThisGribGrid->MCGRIDHEADER[0],ThisGribGrid->MCGRIDHEADER[9], tstr); M0sxtrce(gribdbg); if ( strcmp(tstr,"U ") == 0 || strcmp(tstr,"U") == 0 || strcmp(tstr," U") == 0) { (void)sprintf(gribdbg,"Found u --find v match %p",StructAddress[i]); M0sxtrce(gribdbg); iret = M0GribGetGridHeader(ThisGribGrid,&uGridHeader[0]); iret = M0MatchListuv(StructAddress,uGridHeader); if (iret == 1) { M0sxtrce("Found a matching v grid!"); if (uGridHeader[0] > test) test = uGridHeader[0]; if (numsub > 0) { /* ---> Subsect it before counting <--- */ GridHeadSubSect = (Fint *)malloc(sizeof(int)*64); GridIn = (Fint *)malloc(sizeof(int)*uGridHeader[0]); GridOut= (Fint *)malloc(sizeof(int)*uGridHeader[0]); if (GridHeadSubSect == NULL || GridIn == NULL || GridOut == NULL) return(-20); ok = McSubSectGrid((Fint *)&uGridHeader[0],GridIn, GridHeadSubSect,GridOut, &firstrow, &lastrow, rowinc, &firstcol, &lastcol, colinc, llrc); if (ok != 0) return(-50); memcpy((void *)&uGridHeader[0],GridHeadSubSect,(size_t)256); free(GridIn); free(GridOut); free(GridHeadSubSect); } ngrids += 2; TotBytes += 2*4*uGridHeader[0]; } } } cnt++; i++; if (cnt > 1000000) { (void)sprintf(gribdbg,"Infinite loop?"); M0sxtrce(gribdbg); return(-10); } if (ngrids >= ngrids_to_send) goto EndCount; } goto EndCount; } /* the next code segment only executes if derivation is done on the client */ /* in other words -- the PARSE= string has been passed to the server */ M0sxtrce("Derived grids!"); memcpy( (void *)ThisGD, (void *)GD, sizeof(GridDerive)); memcpy( (void *)CntGD, (void *)GD, sizeof(GridDerive)); /* count the number of grids in GridDerive structure */ TotDerive = 0; while (CntGD != NULL) { TotDerive++; CntGD = CntGD->nextDerive; } (void)sprintf(gribdbg,"TotDerive is %d, ngrids_to_send %d %p", TotDerive,ngrids_to_send,StructAddress[0]); M0sxtrce(gribdbg); ngrids = 0; i = 0; while (StructAddress[i] != (GribGrid_Header *)NULL) { memcpy( (void *)ThisGD, (void *)GD, sizeof(GridDerive)); (void)sprintf(gribdbg," --> Call FindDeriveMatchGridHeader for i = %d >%s< >%s<",i,GD->parm,ThisGD->parm); M0sxtrce(gribdbg); ok = M0FindDeriveMatchGridHeader(StructAddress,Last,i, ThisGD,&GridHeader,&Index); (void)sprintf(gribdbg,"FindDeriveMatchGridDerive returns %d numsub %d Last?: %d %d ",ok,numsub,Last[i],i); M0sxtrce(gribdbg); if (ok == 0 && Last[i] == 1) { /* found the grid -- and all the matching grids needed ** to derive a grid */ (void)sprintf(gribdbg,"Found a %d grid at slot %d that is last ", GridHeader[6],i); M0sxtrce(gribdbg); if (GridHeader[0] > test) test = GridHeader[0]; /* i = Index; */ if (numsub > 0) { /* ---> Subsect it before counting <--- */ GridHeadSubSect = (Fint *)malloc(sizeof(int)*64); GridIn = (Fint *)malloc(sizeof(int)*GridHeader[0]); GridOut= (Fint *)malloc(sizeof(int)*GridHeader[0]); if (GridHeadSubSect == NULL || GridIn == NULL || GridOut == NULL) return(-20); ok = McSubSectGrid(GridHeader,GridIn, GridHeadSubSect,GridOut, &firstrow, &lastrow, rowinc, &firstcol, &lastcol, colinc, llrc); if (ok != 0) return(-50); memcpy((void *)GridHeader,(void *)GridHeadSubSect,256); free(GridIn); free(GridOut); free(GridHeadSubSect); } if (dirget == 1) { ngrids++; TotBytes += 4*GridHeader[0]; } else { ngrids += TotDerive; TotBytes += TotDerive*4*GridHeader[0]; } (void)sprintf(gribdbg,"ngrids found so far: %d %d i is %d %d %d %d", ngrids,ngrids_to_send,i,Last[i], dirget,TotBytes); M0sxtrce(gribdbg); if (ngrids >= ngrids_to_send) goto EndCount; } else { if (ok == 0) { (void)sprintf(gribdbg, "Found a grid at slot %d, but it's not last ",i); M0sxtrce(gribdbg); } } i++; } free(ThisGribGrid); EndCount: ; (void)sprintf(gribdbg,"Cnt is %d ngrids is %d ",cnt,ngrids); M0sxtrce(gribdbg); *Largest = test; *bytes = TotBytes; /*nfiles = 1;*/ return(ngrids); } /* *$ Name: *$ M0AddInfoToGridRequest - add grib information from DSSERVE to *$ Grid Request structure *$ *$ Interface: *$ int M0AddInfoToGridRequest(const char * info, GridRequestObj * GridsR) *$ *$ Input: *$ info - string from INFO= part of dsserve *$ *$ Input and Output: *$ GridsR - Grid Request Object that includes gribgeo/gribmodel info *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - success *$ -10 - malloc error *$ *$ Remarks: *$ INFO= contains database-specific information for the grib server *$ Parse the string to return DATABASE if present, and also the *$ range of grib geographic numbers and the single grib model *$ number. *$ Either GribGeo1 = GribGeo2 or they specify a range of valid numbers. *$ Either GribMdl1 = GribMdl2 or they specify a range of valid numbers. *$ Put the grib information into the GridRequestObj. *$ *$ Categories: *$ grid */ int M0AddInfoToGridRequest(const char * info, GridRequestObj * GridR) { char ** Src; int NSrc; char ** DBNames; int NDBNames = 0; int i; /* loopy bound */ int ok; /* function return values */ int * GribGeoValues; int * GribMdlValues; char ** Ens; int nEns; int * GribType; int nGribType; int nGribGeoValues; int nGribMdlValues; Src = VecNew(); DBNames = VecNew(); Ens = VecNew(); GribGeoValues = (int *)malloc(sizeof(int)*25); GribMdlValues = (int *)malloc(sizeof(int)*25); GribType = (int *)malloc(sizeof(int)*5); if (GribGeoValues == NULL || GribMdlValues == NULL || Ens == NULL || DBNames == NULL ) return(-10); ok = M0GetCArrayFromString(info,"SOURCE","x",&Src,&NSrc); ok = M0GetCArrayFromString(info,"DATAFILE","x",&DBNames,&NDBNames); ok = M0GetCArrayFromString(info,"ENS","x",&Ens,&nEns); /* the lower-case x means undefined in gribland */ ok = M0GetIArrayFromString(info,"GRIBGEO",-1, &GribGeoValues,&nGribGeoValues); ok = M0GetIArrayFromString(info,"GRIBMDL",-1, &GribMdlValues,&nGribMdlValues); ok = M0GetIArrayFromString(info,"GRIBTYPE",1, &GribType,&nGribType); (void)sprintf(gribdbg,"In AddInfoToGridRequest: %d %d %d %d %d GribType: %d", nGribGeoValues,nGribMdlValues,NSrc,nEns,GridR->n_gribgeo, nGribType); M0sxtrce(gribdbg); if (nGribGeoValues > 0 && GridR->n_gribgeo <= 0) { for (i = 0 ; i < nGribGeoValues; i++) { ok = M0IsInArray(GridR->n_gribgeo,GridR->gribgeo,GribGeoValues[i]); if (ok == 1) { /* number there already...do nothing */ M0sxtrce("No Action required"); } else { GridR->gribgeo = M0InsertInIArray(GridR->n_gribgeo,GridR->gribgeo,GribGeoValues[i]); (void)sprintf(gribdbg,"Added GribGeoValues[%d] = %d \n",i,GribGeoValues[i]); M0sxtrce(gribdbg); if (GridR->n_gribgeo > 0) { GridR->n_gribgeo++; } else { GridR->n_gribgeo = 1; } } } } if (nGribMdlValues > 0 && GridR->n_gribmdl <= 0) { for (i = 0; i < nGribMdlValues ; i++) { ok = M0IsInArray(GridR->n_gribmdl,GridR->gribmdl,GribMdlValues[i]); if (ok == 1) { /* number there already...do nothing */ M0sxtrce("No Action required"); } else { GridR->gribmdl = M0InsertInIArray(GridR->n_gribmdl,GridR->gribmdl,GribMdlValues[i]); if (GridR->n_gribmdl > 0) { GridR->n_gribmdl++; } else { GridR->n_gribmdl = 1; } } } } if (NSrc > 0 && GridR->n_src <= 0) { for (i = 0 ; i < NSrc; i++) { ok = M0IsInCArray(GridR->n_src,GridR->source,Src[i]); if (ok == 1) { /* number there already...do nothing */ M0sxtrce("No Action required"); } else { M0sxtrce("Insert in C Array"); GridR->source = M0InsertInCArray(GridR->n_src,GridR->source,Src[i]); (void)sprintf(gribdbg,"Added Source[%d] = %s \n",i,Src[i]); M0sxtrce(gribdbg); if (GridR->n_src > 0) { GridR->n_src++; (void)sprintf(gribdbg,"#Source: %d >%s<",GridR->n_src,GridR->source[GridR->n_src-1]); M0sxtrce(gribdbg); } else { GridR->n_src = 1; (void)sprintf(gribdbg,"#Source: %d >%s<",GridR->n_src,GridR->source[0]); M0sxtrce(gribdbg); } } } } if (nEns > 0 && GridR->n_ens > 0) { /* Add the "default" to the list of ** ens values */ for (i = 0 ; i < nEns; i++) { ok = M0IsInCArray(GridR->n_ens,GridR->ens,Ens[i]); if (ok == 1) { /* number there already...do nothing */ M0sxtrce("No Action required"); } else { M0sxtrce("Insert in C Array"); GridR->ens = M0InsertInCArray(GridR->n_ens,GridR->ens,Ens[i]); (void)sprintf(gribdbg,"Added Ens[%d] = %s \n",i,Ens[i]); M0sxtrce(gribdbg); if (GridR->n_ens > 0) { GridR->n_ens++; (void)sprintf(gribdbg,"#ENS: %d >%s<",GridR->n_ens,GridR->ens[GridR->n_ens-1]); M0sxtrce(gribdbg); } else { GridR->n_ens = 1; (void)sprintf(gribdbg,"#Ens: %d >%s<",GridR->n_ens,GridR->ens[0]); M0sxtrce(gribdbg); } } } } else { if (nEns > 0) { GridR->n_ens = nEns ; GridR->ens = Ens; } } if (nGribType > 0) { GridR->n_type = nGribType; GridR->type = GribType; } if (NDBNames > 0) { GridR->n_DBName = NDBNames; GridR->DBName = DBNames; } return(0); } /* *$ Name: *$ IsGribRequested - is a (single) geographic grib number requested *$ *$ Interface: *$ int IsGribRequested(GridRequestObj *GridR, int GD, int flag) *$ *$ Input: *$ GridR - Grid request object *$ GD - Grid derive object is present (!0) or not (0) *$ flag - check a specified stitching *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ -1 - more than one stitchable group requested *$ -2 - invalid flag *$ 0 - grib value not requested -- do stitching *$ 1 - grib value requested -- don't do stitching *$ *$ Remarks: *$ This function is used to determine whether stitching is required. *$ Check to see if Grib values are requested in the sort strings. *$ Flag can be 0, or 2124, 2526, 3744, 6164, 5678, or 14912. *$ Note that if stitching is to be done, the GridDerive structure exists *$ Non-database: If GD is 1, then parsing is being done. If GD is 2, *$ then stitching; Database: If GD is 1, then parsing. *$ *$ Categories: *$ utility */ int IsGribRequested(GridRequestObj * GridR, int GD, int flag) { int i; int test; int bitcheck = 0; int g3744,g58,g14912,g2124,g2526,g6164; g3744 = g58 = g14912 = g2124 = g2526 = g6164 = 0; (void)sprintf(gribdbg,"In IsGribRequested, n_gribgeo is %d GD %d \n",GridR->n_gribgeo,GD); M0sxtrce(gribdbg); if (GridR->n_gribgeo <= 0) return(0); /* See what the list of GRIB Files includes */ switch (flag) { case 0 : for (i = 0 ; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] >= 37 && GridR->gribgeo[i] <= 44) g3744 = 1; if (GridR->gribgeo[i] >= 21 && GridR->gribgeo[i] <= 24) g2124 = 1; if (GridR->gribgeo[i] >= 25 && GridR->gribgeo[i] <= 26) g2526 = 1; if (GridR->gribgeo[i] >= 61 && GridR->gribgeo[i] <= 64) g6164 = 1; if (GridR->gribgeo[i] >= 5 && GridR->gribgeo[i] <= 8) g58 = 1; if ( (GridR->gribgeo[i] >= 1 && GridR->gribgeo[i] <= 4) || (GridR->gribgeo[i] >= 9 && GridR->gribgeo[i] <= 12) ) g14912 = 1; } break; case 2124: g2124 = 1; break; case 2526: g2526 = 1; break; case 6164: g6164 = 1; break; case 3744: g3744 = 1; break; case 5678: g58 = 1; break; case 14912: g14912 = 1; break; default: return(-2); } /* check to see if a set of stitchable grib values are requested ... ** if so, return 0. Allow for the possibility that other non- ** stitchable values are also requested ****/ /* the tricky part here is that the stitchable values can be in any order */ if (g3744) { /* thinned grib values 37-44 */ for (i = 0; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] >= 37 && GridR->gribgeo[i] <= 44) { bitcheck = bitcheck + (1<<(GridR->gribgeo[i]-37)); (void)sprintf(gribdbg,"bitcheck is %d %d %d ",GridR->gribgeo[i],i,bitcheck); M0sxtrce(gribdbg); } } if (bitcheck == 255 && (GD == 0 || GD == 1|| GD == 2) ) return(0); return(1); } if (g14912) { /* ECMWF grids 1-4/9-12 */ for (i = 0; i < GridR->n_gribgeo ; i++) { if ( (GridR->gribgeo[i] >= 1 && GridR->gribgeo[i] <= 4) || (GridR->gribgeo[i] >= 9 && GridR->gribgeo[i] <= 12) ) { test = GridR->gribgeo[i]; if (test > 8) test -= 4; bitcheck = bitcheck + (1<<(test-1)); (void)sprintf(gribdbg,"bitcheck is %d %d %d %d", GridR->gribgeo[i],test,i,bitcheck); M0sxtrce(gribdbg); } } if (bitcheck == 255 && (GD == 0 || GD == 1|| GD == 2) ) return(0); return(1); } if (g2124 & g2526) { /* both are present */ /* GRIB Values 21-24 and 25-26 .. as in GFS-GLMELRES */ for (i = 0; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] >=21 && GridR->gribgeo[i] <= 26) { bitcheck = bitcheck + (1<<(GridR->gribgeo[i]-21)); (void)sprintf(gribdbg,"bitcheck is %d %d %d ",GridR->gribgeo[i],i,bitcheck); M0sxtrce(gribdbg); } } if (bitcheck == 63 && (GD == 0 || GD == 1|| GD == 2) ) return(0); return(1); } if (g2124) { /* GRIB Values 21-24 */ for (i = 0; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] >=21 && GridR->gribgeo[i] <= 24) { bitcheck = bitcheck + (1<<(GridR->gribgeo[i]-21)); (void)sprintf(gribdbg,"bitcheck is %d %d %d ",GridR->gribgeo[i],i,bitcheck); M0sxtrce(gribdbg); } } if (bitcheck == 15 && (GD == 0 || GD == 1|| GD == 2) ) return(0); return(1); } if (g6164) { /* GRIB Values 61-64 */ for (i = 0; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] >=61 && GridR->gribgeo[i] <= 64) { bitcheck = bitcheck + (1<<(GridR->gribgeo[i]-61)); (void)sprintf(gribdbg,"bitcheck is %d %d %d ",GridR->gribgeo[i],i,bitcheck); M0sxtrce(gribdbg); } } if (bitcheck == 15 && (GD == 0 || GD == 1|| GD == 2) ) return(0); return(1); } if (g58) { /* GRIB Values 5-8 */ for (i = 0; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] >=5 && GridR->gribgeo[i] <= 8) { bitcheck = bitcheck + (1<<(GridR->gribgeo[i]-5)); (void)sprintf(gribdbg,"bitcheck is %d %d %d GD %d",GridR->gribgeo[i],i,bitcheck,GD); M0sxtrce(gribdbg); } } if (bitcheck == 15 && (GD == 0 ||GD == 1|| GD == 2) ) return(0); return(1); } if (g2526) { /* GRIB values 25-26 */ for (i = 0; i < GridR->n_gribgeo ; i++) { if (GridR->gribgeo[i] == 25 || GridR->gribgeo[i] == 26) { bitcheck = bitcheck + (1<<(GridR->gribgeo[i]-25)); (void)sprintf(gribdbg,"bitcheck is %d %d %d ",GridR->gribgeo[i],i,bitcheck); M0sxtrce(gribdbg); } } if (bitcheck == 3 && (GD == 0 || GD == 1|| GD == 2) ) return(0); return(1); } return(1); } /* *$ Name: *$ M0GribFileType -- find what type of GRIB file (1 or 2) *$ *$ Interface: *$ int M0GribFileType(char[ ] filename); *$ *$ Input: *$ filename - fully-resolved file name *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - Unknown type GRIB file *$ 1 - GRIB-1 type file *$ 2 - GRIB-2 type file *$ -1 - unspecified error *$ -10 - could not open file *$ -20 - Failed to malloc space for buffer *$ -30 - Read error *$ -40 - No 'GRIB' in file *$ *$ Remarks: *$ Is the file GRIB-1 or GRIB-2? *$ *$ Categories: *$ utility */ int M0GribFileType(char * filename) { int F2; int ptr; unsigned int FileSize; int GribType; int rc; int sizeleft; struct stat FileStat; unsigned char * buf; /* find size of file and create a buffer large enough to read it */ (void)sprintf(gribdbg,"Check the type of file >%s<",filename); M0sxtrce(gribdbg); GribType = 0; F2 = open(filename,O_RDONLY,0); if (F2 < 0 ) { (void)sprintf(gribdbg,"Error: Could not open file %s ",filename); M0sxtrce(gribdbg); return(-10); } if (stat(filename,&FileStat) < 0) { (void)sprintf(gribdbg, "Error in stat file %s: %d",filename,stat((char *)F2,&FileStat)); M0sxtrce(gribdbg); return(-10); } /* now make a file big enough to hold the GRIB file and read it in!*/ FileSize = FileStat.st_size; buf = (unsigned char *)malloc( FileSize*sizeof(unsigned char)); if (buf == NULL) { (void)sprintf(gribdbg, "Failed making file of size %d bytes ",FileSize); M0sxtrce(gribdbg); return(-20); } (void)sprintf(gribdbg, "Checking Grib type, Made file of size %d bytes ", FileSize); M0sxtrce(gribdbg); rc = read(F2,(void *)buf,FileSize); if (rc < 0) { (void)sprintf(gribdbg,"fread returns error, rc = %d ",rc); M0sxtrce(gribdbg); free(buf); return(-30); } close(F2); sizeleft = FileStat.st_size; ptr = 0; /* we now have the entire grib file in the buffer... *** convert information from grib data to McIDAS grid *** header format...*/ while (sizeleft > 0) { /* the size of the GRIB file is in 3 bytes after ** the characters 'GRIB' in the grib file...find it */ while (buf[ptr] != 'G') { ptr++; if (ptr >= FileSize) { free(buf); return(-40); } } if (buf[ptr] == 'G' && buf[ptr+1] == 'R' && buf[ptr+2] == 'I' && buf[ptr+3] == 'B') { /* we've found "GRIB"...the grib type is slot 7 */ GribType = M0MakeInt((unsigned char *)&buf[ptr+7],1); free(buf); return(GribType); } else { ptr++; } } free(buf); return(-1); } /* *$ Name: *$ M0FreeGribGrid - Free a stack of structures *$ *$ Interface: *$ integer function *$ M0FreeGribGrid(GribGrid_Header *First, GribGrid_Header *Last) *$ *$ Input: *$ First - first structure in stack *$ Last - last structure in stack *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - success *$ -1 - Failure in malloc *$ *$ Remarks: *$ Free all the structures in a stack, including *$ the top and last structure *$ *$ Categories: *$ utility */ int M0FreeGribGrid(GribGrid_Header *Top, GribGrid_Header *Last) { GribGrid_Header * TNode1; GribGrid_Header * TNode2; char gribdbg[256]; TNode1 = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); TNode2 = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); memset(TNode1,0,sizeof(GribGrid_Header)); memset(TNode2,0,sizeof(GribGrid_Header)); if (TNode1 == NULL || TNode2 == NULL) return(-1); TNode1 = Top; TNode2 = Top->nextGribGrid; while (TNode1 != NULL) { free(TNode1); if (TNode2 == NULL) break; TNode1 = TNode2; if (TNode1 != NULL) TNode2 = TNode1->nextGribGrid; } M0sxtrce("return"); return(0); } /* *$ Name: *$ M0MatchGribNumberRequest - do grib numbers in INFO= match request? *$ *$ Interface: *$ integer function *$ M0MatchGribNumberRequest(char * Info, GribGrid_Request *GridR) *$ *$ Input: *$ First - first structure in stack *$ Last - last structure in stack *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - There are no GRIB requests conflicting with INFO= *$ -1 - Failure in malloc *$ <-2000 - grib model value abs(2000+rc) is invalid *$ <-1000 - grib geo value abs(1000+rc) is invalid *$ *$ Remarks: *$ Free all the structures in a stack, including *$ the top and last structure *$ *$ Categories: *$ utility */ int M0MatchGribNumberRequest(char *info, GridRequestObj *GR) { int rc = 0; char * DataBase; int GribGeoNum; int GribMdlNum; int * GribGeoList; int * GribMdlList; int i,j,k; /* loop bounds */ int jcheck; /* value to check against*/ int Match; /* did things match? */ DataBase = (char *)malloc(sizeof(char)*512); GribGeoList = (int *)malloc(sizeof(int)*512); GribMdlList = (int *)malloc(sizeof(int)*512); if (DataBase == NULL || GribGeoList == NULL || GribMdlList == NULL) { return(-1); } (void)sprintf(gribdbg,"info is >%s< with length %d",info,strlen(info)); M0sxtrce(gribdbg); if (info == NULL || strlen(info) == 0 || strcmp(info," ") == 0) return(0); rc = M0GetIArrayFromString(info,"GRIBGEO",-1, &GribGeoList,&GribGeoNum); rc = M0GetIArrayFromString(info,"GRIBMDL",-1, &GribMdlList,&GribMdlNum); if (GR->n_gribgeo > 0 && GribGeoNum > 0) { /* make sure Grid Request grib geos match thoses ** available in the info= keyword */ for (i = 0; i < GR->n_gribgeo; i++) { Match = 0; /* a user may have entered a "special" grib geo code -- 2124/2526/3744/5678/6164/14912 -- check */ if (GR->gribgeo[i] > 255) { switch (GR->gribgeo[i]) { case 2124 : for (j = 21; j <=24; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 2526 : for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == 25 || GribGeoList[k] == 26) Match = 1; } break; case 3744 : for (j = 37; j <=44; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 5678 : for (j = 5; j <=8; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 6164 : for (j = 61; j <=64; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 14912: for (j = 1; j <=8; j++) { jcheck = j; if (j > 4) jcheck = j+4; for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == jcheck) Match = 1; } } break; default : Match = 0; } } else { for (j = 0; j < GribGeoNum; j++) { if (GribGeoList[j] == GR->gribgeo[i]) Match = 1; } } if (Match == 0) return(-1000 - GR->gribgeo[i]); } } if (GR->n_gribmdl > 0 && GribMdlNum > 0) { /* make sure Grid Request grib geos match thoses ** available in the info= keyword */ for (i = 0; i < GR->n_gribmdl; i++) { Match = 0; for (j = 0; j < GribMdlNum; j++) { if (GribMdlList[j] == GR->gribmdl[i]) Match = 1; } if (Match == 0) return(-20000 - GR->gribmdl[i]); } } return(0); } /* *$ Name: *$ M0MatchGribNumberDerive - do grib numbers in INFO= match request? *$ *$ Interface: *$ integer function *$ M0MatchGribNumberDerive(char * Info, GribDerive *GridR) *$ *$ Input: *$ First - first structure in stack *$ Last - last structure in stack *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - There are no GRIB requests conflicting with INFO= *$ -1 - Failure in malloc *$ <-1000 - grib geo value abs(1000+rc) is invalid *$ *$ Remarks: *$ If stitchable grids are requested, a derive structure is *$ created. Make sure the GRIB numbers in the stitchable *$ grid match those in the derive structure *$ *$ Categories: *$ utility */ int M0MatchGribNumberDerive(char *info, GridDerive *GD) { int rc = 0; char * DataBase; GridDerive * ThisGribGridDerive; int GribGeoNum; int GribMdlNum; int * GribGeoList; int * GribMdlList; int i,j,k; /* loop bounds */ int jcheck; /* value to check */ int Match; /* did things match? */ DataBase = (char *)malloc(sizeof(char)*512); GribGeoList = (int *)malloc(sizeof(int)*512); GribMdlList = (int *)malloc(sizeof(int)*512); ThisGribGridDerive = (GridDerive *)malloc(sizeof(GridDerive)); if (DataBase == NULL || GribGeoList == NULL || GribMdlList == NULL || ThisGribGridDerive == NULL ) { return(-1); } ThisGribGridDerive = GD; rc = M0GetIArrayFromString(info,"GRIBGEO",-1, &GribGeoList,&GribGeoNum); rc = M0GetIArrayFromString(info,"GRIBMDL",-1, &GribMdlList,&GribMdlNum); (void)sprintf(gribdbg,"GribNumberRequest, GribGeoNum %d GribMdlNum %d\n", GribGeoNum,GribMdlNum); M0sxtrce(gribdbg); for (rc = 0; rc < GribGeoNum ; rc++) { (void)sprintf(gribdbg,"GeoNum %d is %d \n",rc,GribGeoList[rc]); M0sxtrce(gribdbg); } (void)sprintf(gribdbg,"ThisGribGridDerive: %x %x ",GD,ThisGribGridDerive); M0sxtrce(gribdbg); /* see if Grid Derive structure contains a series of geo grib number */ if (GribGeoNum == 0) return(0); while (ThisGribGridDerive != NULL) { /* make sure Grid Request grib geos match thoses ** available in the info= keyword */ (void)sprintf(gribdbg,"Thisgeo is %d ",ThisGribGridDerive->gribgeo); M0sxtrce(gribdbg); if (ThisGribGridDerive->gribgeo > 0) { Match = 0; for (i = 0; i < GribGeoNum; i++) { (void)sprintf(gribdbg,"i is %d %d %d \n",i,GribGeoList[i], ThisGribGridDerive->gribgeo); M0sxtrce(gribdbg); if (GribGeoList[i] == ThisGribGridDerive->gribgeo) Match = 1; } if (ThisGribGridDerive->gribgeo > 255) { switch (ThisGribGridDerive->gribgeo) { case 2124 : for (j = 21; j <=24; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 2526 : for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == 25 || GribGeoList[k] == 26) Match = 1; } break; case 3744 : for (j = 37; j <=44; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 5678 : for (j = 5; j <=8; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 6164 : for (j = 61; j <=64; j++) { for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == j) Match = 1; } } break; case 14912: for (j = 1; j <=8; j++) { jcheck = j; if (j > 4) jcheck = j+4; for (k = 0; k < GribGeoNum; k++) { if (GribGeoList[k] == jcheck) Match = 1; } } break; default : Match = 0; } } if (Match == 0) return(-1000 - ThisGribGridDerive->gribgeo); } ThisGribGridDerive = ThisGribGridDerive->nextDerive; } return(0); } /* *$ Name: *$ M0ListStructIndex - debug to list out StructIndex ordered values *$ *$ Interface: *$ integer function *$ M0ListStructIndex(GribGrid_Header ** StructIndex, int * Last) *$ *$ Input: *$ First - first structure in stack *$ Last - last structure in stack *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - There are no GRIB requests conflicting with INFO= *$ -1 - Failure in malloc *$ <-1000 - grib geo value abs(1000+rc) is invalid *$ *$ Remarks: *$ If stitchable grids are requested, a derive structure is *$ created. Make sure the GRIB numbers in the stitchable *$ grid match those in the derive structure *$ *$ Categories: *$ utility */ int M0ListStructIndex(GribGrid_Header ** StructIndex, int * LastStitch) { int i = 0; GribGrid_Header * ThisGribGrid; ThisGribGrid = (GribGrid_Header *)malloc(sizeof(GribGrid_Header)); while ( StructIndex[i] != (GribGrid_Header *)NULL ) { memcpy( (void *)ThisGribGrid,(void *)StructIndex[i], sizeof(GribGrid_Header)); (void)sprintf(gribdbg,"List Struct Index %d %p Last %d Geo %d Par %d par %d lev %d", i,StructIndex[i],LastStitch[i],ThisGribGrid->MCGRIDHEADER[48], ThisGribGrid->MCGRIDHEADER[19],ThisGribGrid->MCGRIDHEADER[6], ThisGribGrid->MCGRIDHEADER[9]); M0sxtrce(gribdbg); i++; } return(0); } /* *$ Name: *$ M0ListStitchIt - change grib geo number in GridHeader? *$ *$ Interface: *$ integer function *$ M0ListStitchIt(GridRequestObj * GridR, int GD, int Grid48, int Grid50, int Grid32) *$ *$ Input: *$ GridR - Grid request object containing input grib geo sorts *$ GD - Grid Derive object present (!0) or not (0) *$ Grid48 - geo grib value in header slot 48 *$ Grid50 - model grib value in header slot 50 *$ Grid32 - source in header slot 32 *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ >0 - grib geo value in slot 48 *$ 0 - Should change grid header 48 to reflect stitching *$ *$ Remarks: *$ See if the listing should be for a stitched grid *$ *$ Categories: *$ utility */ int M0ListStitchIt(GridRequestObj * GridR, int GD, int Grid48, int Grid50, int Grid32) { /* The value of slot 48 in the grid header should be changed if ** it's stitchable and all or none of the stitchable components ** have been requested **/ char model[5]; memcpy((void *)&model[0],(void *)&Grid32,4); model[4] = (char)0; (void)sprintf(gribdbg,"Into ListStitchIt as %d %s\n",Grid48,model); M0sxtrce(gribdbg); switch (Grid48) { case 21: case 22: case 23: case 24: if (GridR->n_gribgeo == 0) return(2124); else { if (IsGribRequested(GridR,GD,2124) == 0) return(2124); } break; case 25: case 26: if (GridR->n_gribgeo == 0) return(2526); else { if (IsGribRequested(GridR,GD,2526) == 0) return(2526); } break; case 61: case 62: case 63: case 64: if (GridR->n_gribgeo == 0) return(6164); else { if (IsGribRequested(GridR,GD,6164) == 0) return(6164); } break; case 37: case 38: case 39: case 40: case 41: case 42: case 43: case 44: if (GridR->n_gribgeo == 0) return(3744); else { if (IsGribRequested(GridR,GD,3744) == 0) return(3744); } break; case 5: case 6: case 7: case 8: if (Grid50 == 127 || Grid50 == 128 || strcmp(model,"ECMF") == 0) { if (GridR->n_gribgeo == 0) return(5678); else { if (IsGribRequested(GridR,GD,5678) == 0) return(5678); } } break; case 1: case 2: case 3: case 4: case 9: case 10: case 11: case 12: if (Grid50 == 127 || Grid50 == 128 || strcmp(model,"ECMF") == 0) { if (GridR->n_gribgeo == 0) return(14912); else { if (IsGribRequested(GridR,GD,14912) == 0) return(14912); } } break; default: return(Grid48); } return(Grid48); } /* *$ Name: *$ M0TraceGD -- write out the grid derive structure *$ *$ Interface: *$ integer function *$ M0TraceGD(GridDerive *GD) *$ *$ Input: *$ GD - grid derive structure *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ >0 - grib geo value in slot 48 *$ 0 - Should change grid header 48 to reflect stitching *$ *$ Remarks: *$ See if the listing should be for a stitched grid *$ *$ Categories: *$ utility */ int M0TraceGD(GridDerive * GD) { /* The value of slot 48 in the grid header should be changed if ** it's stitchable and all or none of the stitchable components ** have been requested **/ M0sxtrce("These are the values in the GridDerive structure"); (void)sprintf(gribdbg," Present? %d Day %d Time %d Fhour %d Grid %d", GD->present,GD->day,GD->time,GD->fhour,GD->grid); M0sxtrce(gribdbg); (void)sprintf(gribdbg,"Grib #s: %d %d %d %d ", GD->gribgeo,GD->gribmdl,GD->gribpar,GD->griblev); M0sxtrce(gribdbg); (void)sprintf(gribdbg,"Level >%s< parm >%s< proj >%s< source >%s< Levelunit >%s<", GD->level,GD->parm,GD->proj,GD->src,GD->levelunit); M0sxtrce(gribdbg); M0sxtrce("End of List"); return(0); } /* *$ Name: *$ M0GetNavFromGribTemplate - Get McIDAS grid header information out *$ of a structure created by grib2 libraries *$ *$ Interface: *$ int M0GetNavFromGribTemplate( int TemplNum, int * Template, *$ Fint ** GridHeader, int *ScanMode) *$ *$ Input: *$ TemplNum - template number *$ Template - Template created by grib2 libraries *$ *$ Input and Output: *$ none *$ *$ Output: *$ GridHeader - McIDAS gridheader *$ ScanMode - Scanmode of data *$ *$ Return values: *$ 0 - success. *$ -12 - unknown template number *$ -50 - malloc error *$ *$ Remarks: *$ Creates a McIDAS grid header for 1 grib2 message. *$ Not all template numbers can be decoded *$ *$ Categories: *$ grid */ int M0GetNavFromGribTemplate(g2int TemplNum, g2int * Template, Fint ** GridHeader, int *ScanMode) { int ok; g2int NPts_Along_Xaxis; g2int NPts_Along_Yaxis; int FirstLatPoint; int FirstLonPoint; int XDirectionGridLength; int YDirectionGridLength; int StandardLon; int StandardLat1; int StandardLat2; float FLat1stGridPoint; float FLon1stGridPoint; float FloatDX; float FloatDY; float FStdLat1; float FStdLat2; float FStdLon; float xrow,xcol; double ele_0,lin_0; double DLat_FirstGridPoint; double DLon_FirstGridPoint; double DdX; double DStdLat1; double DStdLat2; double DStdLon; int I_X_increase; int J_Y_increase; int X_Y_adjacent; int FlipScan; Fint * McGridNav; int local=0; McGridNav = (Fint *)malloc(sizeof(Fint)*HEDSIZ); if (McGridNav == (Fint *) NULL) return(-50); memset(McGridNav,0,HEDSIZ*sizeof(Fint)); NPts_Along_Xaxis = Template[7]; NPts_Along_Yaxis = Template[8]; if ( Template == NULL) { (void)sprintf(gribdbg,"M0GetNavFromGribTemplate null pointer \n"); M0sxtrce(gribdbg); } (void)sprintf(gribdbg,"M0GetNavFromGribTemplate TemplNum %d \n",TemplNum); M0sxtrce(gribdbg); local = TemplNum; switch (local) { case 0: McGridNav[1] = NPts_Along_Yaxis; McGridNav[2] = NPts_Along_Xaxis; McGridNav[0] = McGridNav[1]*McGridNav[2]; McGridNav[33] = 1; /* McIDAS expects longitudes to be between +/- 180 .. make it so */ McGridNav[35] = -(McIntLon((float)(Template[12]/1000000.))); McGridNav[37] = -(McIntLon((float)(Template[15]/1000000.))); McGridNav[34] = Template[11]/100; /* Latitude of first point */ McGridNav[36] = Template[14]/100; /* Latitude of last point */ McGridNav[38] = Template[17]/100; /* increment in j direction */ McGridNav[39] = Template[16]/100; /* increment in i direction */ *ScanMode = Template[18]; /* ScanMode flip needed for NHME grids */ if ((*ScanMode & 64)/64 == 1) { McGridNav[34] = Template[14]/100; McGridNav[36] = Template[11]/100; (void)sprintf(gribdbg,"McGridNav 34 is >%d<, 36 is >%d<",McGridNav[34],McGridNav[36]); M0sxtrce(gribdbg); } (void)sprintf(gribdbg,"ScanMode 0 is >%d<",ScanMode); M0sxtrce(gribdbg); if (McGridNav[38] != McGridNav[39]) McGridNav[33] = 4; break; case 10: /*#define p(x) log((1.+sin(d2r*x))/cos(d2r*x))*/ /* Mercator ...True Mercator is not yet supported in McIDAS ..*/ /* McGridNav[1] = NPts_Along_Yaxis; McGridNav[2] = NPts_Along_Xaxis; McGridNav[0] = McGridNav[1]*McGridNav[2]; McGridNav[33] = 4; */ /*FirstLatPoint=Template[9]; FirstLonPoint=Template[10]; LatD=Template[12]; LastLatPoint=Template[13]; LastLonPoint=Template[14]; calcTemp1=p(FirstLatPoint*0.000001); calcTemp2=p(LastLatPoint*0.0000001); lin_0 = NPts_Along_Yaxis + NPts_Along_Yaxis*calcTemp1/(calcTemp2-calcTemp1); ele_0 = (double)((NPts_Along_Xaxis)-1)/2.;*/ /* *ScanMode = Template[15]; I_X_increase = (*ScanMode & 128)/128; J_Y_increase = (*ScanMode & 64)/64; X_Y_adjacent = (*ScanMode & 32)/32; FlipScan = (*ScanMode & 16)/16 ; */ /* XDirectionGridLength = Template[17]; YDirectionGridLength = Template[18]; FloatDX = XDirectionGridLength/1000000.; km FloatDY = YDirectionGridLength/1000000.; km */ /*McGridNav[34] = (Fint) lin_0; McGridNav[35] = (Fint) ele_0; McGridNav[36] = LatD; McGridNav[37] = FirstLonPoint - (FirstLonPoint-LastLonPoint)/2.; */ /* McIDAS expects longitudes to be between +/- 180 .. make it so */ /* McGridNav[37] = McIntLon((float)(Template[10]/1000000.)); McGridNav[35] = McIntLon((float)(Template[14]/1000000.)); McGridNav[34] = Template[9]/100; Latitude of first point McGridNav[36] = Template[13]/100; Latitude of last point McGridNav[38] = (Fint) FloatDX; McGridNav[39] = (Fint) FloatDY; if (McGridNav[38] == McGridNav[39]) McGridNav[33] = 1; */ free (McGridNav); M0sxtrce("True Merc not supported in McIDAS"); return(-12); break; case 20: /* Polar stereographic projection */ McGridNav[1] = NPts_Along_Yaxis; McGridNav[2] = NPts_Along_Xaxis; McGridNav[0] = McGridNav[1]*McGridNav[2]; McGridNav[33] = 2; FirstLatPoint = Template[9]; FirstLonPoint = Template[10]; StandardLat1 = Template[12]; StandardLon = Template[13]; XDirectionGridLength = Template[14]; YDirectionGridLength = Template[15]; FLat1stGridPoint = FirstLatPoint/1000000.; FLon1stGridPoint = 360. - FirstLonPoint/1000000.; FloatDX = XDirectionGridLength/1000000.; /* km */ FloatDY = YDirectionGridLength/1000000.; /* km */ FStdLat1 = StandardLat1/1000000.; FStdLat2 = FStdLat1; FStdLon = 360. - (StandardLon /1000000.); xrow = 1; xcol = NPts_Along_Yaxis; FloatDX *= 1000.; FloatDY *= 1000.; DStdLat1 = (double)FStdLat1; DStdLat2 = (double)FStdLat2; DStdLon = (double)FStdLon; DdX = (double) FloatDX; DLat_FirstGridPoint = (double)FLat1stGridPoint; DLon_FirstGridPoint = (double)FLon1stGridPoint; ok = M0FindRowColNPole(NPts_Along_Yaxis,NPts_Along_Xaxis,"POLAR", DStdLat1,DStdLat2,DStdLon,DdX, DLat_FirstGridPoint,DLon_FirstGridPoint, &ele_0,&lin_0); McGridNav[34] = (Fint)(ele_0); McGridNav[35] = (Fint)(lin_0); McGridNav[36] = (Fint)(FloatDX); McGridNav[37] = (Fint)(FStdLon*10000); McGridNav[38] = (Fint)(FStdLat1*10000); McGridNav[39] = (Fint)(FStdLat1*10000); *ScanMode = Template[17]; I_X_increase = (*ScanMode & 128)/128; J_Y_increase = (*ScanMode & 64)/64; X_Y_adjacent = (*ScanMode & 32)/32; FlipScan = (*ScanMode & 16)/16 ; (void)sprintf(gribdbg,"ScanMode 20 is %d %d %d >%d<",*ScanMode, I_X_increase,J_Y_increase,X_Y_adjacent); M0sxtrce(gribdbg); break; case 30: /* Lambert Comformal!!! */ McGridNav[1] = NPts_Along_Yaxis; McGridNav[2] = NPts_Along_Xaxis; McGridNav[0] = McGridNav[1]*McGridNav[2]; McGridNav[33] = 6; FirstLatPoint = Template[9]; FirstLonPoint = 360000000 - Template[10]; XDirectionGridLength = Template[14]; YDirectionGridLength = Template[15]; StandardLon = 360000000 - Template[13]; StandardLat1 = Template[18]; StandardLat2 = Template[19]; FLat1stGridPoint = FirstLatPoint/1000000.; FLon1stGridPoint = FirstLonPoint/1000000.; FloatDX = XDirectionGridLength/1000000.; /* km */ FloatDY = YDirectionGridLength/1000000.; /* km */ FStdLat1 = StandardLat1/1000000.; FStdLat2 = StandardLat2/1000000.; FStdLon = StandardLon /1000000.; xrow = 1; xcol = NPts_Along_Yaxis; FloatDX *= 1000.; FloatDY *= 1000.; DdX = FloatDX; DStdLat1 = (double) FStdLat1; DStdLat2 = (double) FStdLat2; DStdLon = (double) FStdLon ; DLat_FirstGridPoint = (double) FLat1stGridPoint; DLon_FirstGridPoint = (double) FLon1stGridPoint; ok = M0FindRowColNPole(NPts_Along_Yaxis,NPts_Along_Xaxis,"LAMBERT", DStdLat1,DStdLat2,DStdLon,DdX, DLat_FirstGridPoint,DLon_FirstGridPoint, &ele_0,&lin_0); McGridNav[34] = (Fint)(ele_0); McGridNav[35] = (Fint)(lin_0); McGridNav[36] = (Fint)(FloatDX); McGridNav[37] = (Fint)(FStdLon*10000); McGridNav[38] = (Fint)(FStdLat1*10000); McGridNav[39] = (Fint)(FStdLat2*10000); *ScanMode = Template[17]; I_X_increase = (*ScanMode & 128)/128; J_Y_increase = (*ScanMode & 64)/64; X_Y_adjacent = (*ScanMode & 32)/32; FlipScan = (*ScanMode & 16)/16 ; (void)sprintf(gribdbg,"ScanMode 30 is %d %d %d >%d<",*ScanMode, I_X_increase,J_Y_increase,X_Y_adjacent); M0sxtrce(gribdbg); break; default: free (McGridNav); return(-12); } *GridHeader = McGridNav; (void)sprintf(gribdbg,"M0GetNavFromGribTemplate exit \n"); M0sxtrce(gribdbg); return(0); } /* *$ Name: *$ M0GetProductInfoTemplate00 - get the parameter/unit information *$ *$ Interface: *$ integer function *$ M0GetProductInfoTemplate00(int * Template, int GenCenter, char ** Par, *$ int * Par4, char ** unit, int * unit4, double * Lev1, *$ double * Lev2, int * LevUnit, int * ModelName) *$ *$ Input: *$ Template - Template containing metadata information *$ GenCenter - generating center ID *$ *$ Input and Output: *$ none *$ *$ Output: *$ Par - name of gridded parameter in GRIB2 message *$ Par4 - lit of 4-char name of gridded parameter in GRIB2 message *$ unit - units of gridded parameter in GRIB2 message *$ unit4 - lit of 4-char units of gridded parameter in GRIB2 message *$ Lev1 - level of data *$ Lev2 - 2nd level that defines layer *$ LevUnit - lit of units of level *$ ModelName - lit of model name *$ *$ Return values: *$ 0 - success *$ -10 - Product Template number not yet implemented *$ -12 - non-NCEP grid *$ *$ Remarks: *$ Extract the parameter and units from the Product_Definition_Section *$ Lev2 is NULL if data are on one level, else Lev2 is top level *$ *$ Categories: *$ utility */ int M0GetProductInfoTemplate00(g2int * Template, g2int GenCenter, char ** Pstring, int * Pstring4, char ** Ustring, int * Ustring4, double * Lev1, double * Lev2, int * LevUnit, int * iModelName, int * fhour) { int ParameterCategory = Template[0]; /* Major Category */ int ParameterNumber = Template[1]; /* Minor category */ int NumberBands; int rc; int GeneratingProcess = Template[2]; int BackgroundProcess = Template[3]; int ForecastProcess = Template[4]; int HoursAfterRefTime = Template[5]; int MinutesAfterRefTime = Template[6]; int TimeUnitIndicator = Template[7]; int ForecastTime = Template[8]; double Level1, Level2, Level1Scale, Level2Scale; int LUnit1=0; /* lit of the unit string for the level */ int LUnit2=0; /* lit of the unit string for the level */ int FirstFixedSfcType = Template[9]; int FirstFixedSfcScale = Template[10]; int FirstFixedSfc = Template[11]; int SecondFixedSfcType = Template[12]; int SecondFixedSfcScale = Template[13]; int SecondFixedSfc = Template[14]; int Model=0; /* lit of forecast model used */ int FHOUR=0; char * Parameter; char * Parameter4; char * Unit; char * Unit4; char * MajorValue[] = {"Temperature","Moisture","Momentum","Mass", "Short-wave Radiation","Long-wave Radiation", "Cloud","Thermodynamic Stability Indices", "Kinematic Stability Indices","Temperature Probabilities", "Moisture Probabilities","Momentum Probabilities", "Aerosols","Trace Gases","Radar","Forecast Radar Imagery", "Electro-dynamics","Nuclear/radiology", "Physical atmospheric properties"}; char * ModelName; if (GenCenter == 7) { /* NCEP */ rc = M0Grib2GetNCEPModelName(ForecastProcess, &Model, &ModelName); } else { (void)sprintf(gribdbg,"Non-ncep grid! \n\n\n"); M0sxtrce(gribdbg); return(-12); } (void)M0ListOutGeneratingProcess(GeneratingProcess); rc = M0GetRealForecastTime(TimeUnitIndicator,ForecastTime,&FHOUR); rc = M0Grib2GetLevelInfo(FirstFixedSfcType,FirstFixedSfc,FirstFixedSfcScale, &Level1,&Level2Scale,&LUnit1); rc = M0Grib2GetLevelInfo(SecondFixedSfcType,SecondFixedSfc,SecondFixedSfcScale, &Level2,&Level2Scale,&LUnit2); rc = M0Grib2GetParameterString (ParameterCategory, ParameterNumber, &Parameter,&Parameter4,&Unit,&Unit4); *Pstring = Parameter; (void)sprintf(gribdbg,"Parameter string is >%s<>%s< ",Parameter,*Pstring); M0sxtrce(gribdbg); *Pstring4 = lit_(Parameter4,4); *Ustring = Unit; *Ustring4 = lit_(Unit4,4); *Lev1 = Level1; *Lev2 = Level2; *LevUnit = LUnit1; *iModelName = Model; *fhour = FHOUR; return(0); } /* *$ Name: *$ M0GetMeanMaxMinScale - get statistical attributes of an array *$ *$ Interface: *$ integer function *$ M0GetMeanMaxMinScale(float * Values, Fint * Header, *$ double * Mean, double * Max, double * Min, int * Scale) *$ *$ Input: *$ Values - array of float values *$ Header - McIDAS grid header *$ *$ Input and Output: *$ none *$ *$ Output: *$ Mean - mean value of all data *$ Max - max value of data *$ Min - min value of data *$ Scale - scale factor that best fits the data *$ *$ Return values: *$ 0 - success *$ *$ Remarks: *$ Get the scale of the data. Calls the fortran function m0grdsca *$ *$ Categories: *$ utility */ int M0GetMeanMaxMinScale(float * Values, Fint * Header, double * Mean, double * Max, double * Min, int *Scale) { int scale; int i; double HoldMean; double HoldMax = -10000.; double HoldMin = 10000.; double Sum = 0.; double * Test; Test = (double *)malloc(sizeof(double)*Header[0]); if (Test == NULL) return(-5); for (i = 0 ; i < Header[0]; i++) Test[i] = (double)Values[i]; scale = m0grdsca(Test,Header[0]); free(Test); HoldMax = -10000; HoldMin = 10000; for (i = 0; i < Header[0]; i++) { Sum += Values[i]; if (Values[i] > HoldMax) HoldMax = Values[i]; if (Values[i] < HoldMin) HoldMin = Values[i]; } HoldMean = Sum/(Header[0]); *Max = HoldMax; *Min = HoldMin; *Mean = HoldMean; *Scale = scale; return(0); } /* *$ Name: *$ M0GetProductInfoTemplate - get the parameter/unit information *$ *$ Interface: *$ integer function *$ M0GetProductInfoTemplate(int TemplateNum, int * Template, *$ int GenCenter, int Discipline, char ** Par, *$ int * Par4, char ** unit, int * unit4, double * Lev1, *$ double * Lev2, int * LevUnit, int * ModelName, *$ int * fhour, int * generatingProcess) *$ *$ Input: *$ TemplateNum - The product definition section template number *$ Template - Template containing metadata information *$ GenCenter - generating center ID *$ Discipline - the Discipline of the data - 0=Meterological Products *$ 1=Hydrological Products *$ 2=Land surface Products *$ 3=Space Products *$ 10=Oceanographic Products *$ *$ Input and Output: *$ none *$ *$ Output: *$ Par - name of gridded parameter in GRIB2 message *$ Par4 - lit of 4-char name of gridded parameter in GRIB2 message *$ unit - units of gridded parameter in GRIB2 message *$ unit4 - lit of 4-char units of gridded parameter in GRIB2 message *$ Lev1 - level of data *$ Lev2 - 2nd level that defines layer *$ LevUnit - lit of units of level *$ ModelName - lit of model name *$ FHour - the forecast hour *$ ForecastProcess - Forecast Generation Identifier defined by originating center *$ ensembleString - default string of "none", otherwise the ensemble info *$ *$ Return values: *$ 0 - success *$ -10 - Product Template number not yet implemented *$ -12 - non-NCEP grid *$ *$ Remarks: *$ Extract the parameter and units from the Product_Definition_Section *$ Lev2 is NULL if data are on one level, else Lev2 is top level *$ *$ Categories: *$ utility */ int M0GetProductInfoTemplate(g2int templateNum, g2int * Template, g2int GenCenter, g2int Discipline, char ** Pstring, int * Pstring4, char ** Ustring, int * Ustring4, double * Lev1, double * Lev2, int * Lev1Type, int * Lev2Type, int * LevUnit, int * LevScale, int * iModelName, int * fhour, int * ForecastProcess, int * ensembleString) { static short int first_call = 1; static int n_gb2parm; /* # of GRIB parameter table entries */ static int n_gb2model; /* # of GRIB NCEP model entries */ static GB2PARMTAB *parmList = NULL; /* list of available parameters */ static GB2MODELTAB *modelList = NULL; /* list of available models */ int ParameterCategory = Template[0]; /* Major Category */ int ParameterNumber = Template[1]; /* Minor category */ int GeneratingProcess = Template[2]; int NumberBands; int rc; int BackgroundProcess = Template[3]; int HoursAfterRefTime = Template[5]; int MinutesAfterRefTime = Template[6]; int TimeUnitIndicator = Template[7]; int ForecastTime = Template[8]; double Level1, Level2, Level1Scale, Level2Scale; int LUnit1=0; /* lit of the unit string for the level */ int LUnit2=0; /* lit of the unit string for the level */ int FirstFixedSfcType = Template[9]; int FirstFixedSfcScale = Template[10]; int FirstFixedSfc = Template[11]; int SecondFixedSfcType = Template[12]; int SecondFixedSfcScale = Template[13]; int SecondFixedSfc = Template[14]; /* <<<<< UPC mod 20080803 - 'int Model=8' -> 'char *Model=NULL' >>>>> */ char *Model=NULL; /* pointer to short name of forecast model */ int FHOUR=0; char * Parameter; char * Parameter4; char * Unit; char * Unit4; char ens[5]; char * MajorValue[] = {"Temperature","Moisture","Momentum","Mass", "Short-wave Radiation","Long-wave Radiation", "Cloud","Thermodynamic Stability Indices", "Kinematic Stability Indices","Temperature Probabilities", "Moisture Probabilities","Momentum Probabilities", "Aerosols","Trace Gases","Radar","Forecast Radar Imagery", "Electro-dynamics","Nuclear/radiology", "Physical atmospheric properties"}; char * ModelName; if (first_call) { first_call = 0; rc = load_gb2parmtab(&n_gb2parm, &parmList); rc = load_gb2modeltab(&n_gb2model, &modelList); } *ForecastProcess = Template[4]; if (GenCenter == 7) { /* NCEP */ /* rc = M0Grib2GetNCEPModelName(*ForecastProcess, &Model, &ModelName); */ rc = grb2ModelLookup(n_gb2model,modelList,*ForecastProcess, &ModelName,&Model); /* <<<<< UPC add 20080803 - let the user know that grb2ModelLookup failed to find the model. Exactly what to do at this point is unclear. Saying it is a non-NCEP grid seems safe >>>>> */ if ( rc != 0 ) { Mceprintf( "M0GetProductInfoTemplate: grb2ModelLookup returned %d\n", rc ); return(-12); } } else if (GenCenter == 8) { ModelName = "National Digital Forecast Database (NWSTG)"; Model = "NDFD"; } else if (GenCenter == 74) { ModelName = "UK Meteorological Office - Bracknell (RSMC)"; Model = "UKMT"; } else if (GenCenter == 98) { ModelName = "European Center for Medium Range Forecasts (RSMC)"; Model = "ECMF"; } else { (void)sprintf(gribdbg,"Non-NCEP grid, Generating Center = %d",GenCenter); M0sxtrce(gribdbg); Mcprintf("Non-NCEP grid, Generating Center = %d\n", GenCenter); return(-12); } (void)M0ListOutGeneratingProcess(GeneratingProcess); rc = M0GetRealForecastTime(TimeUnitIndicator,ForecastTime,&FHOUR); *fhour = FHOUR; /* Product Def Template 4.1 is ensembles */ if (templateNum == 1) { switch(Template[15]) { case 0: (void)sprintf(ens,"+0 "); break; case 1: (void)sprintf(ens,"-0 "); break; case 2: (void)sprintf(ens,"-%i",Template[16]); break; case 3: (void)sprintf(ens,"+%i",Template[16]); break; default: (void)sprintf(ens,"none"); } } /* Derived forecasts - put in ensemble field for now */ else if (templateNum == 2 || templateNum==3 || templateNum==4) { switch(Template[15]) { case 0: /* Unweighted Mean of All Members */ (void)sprintf(ens,"dunw"); break; case 1: /* Weighted Mean of All Members */ (void)sprintf(ens,"dwgt"); break; case 2: /* Standard deviation with respect to cluster mean */ (void)sprintf(ens,"dstd"); break; case 3: /* Standard deviation with respect to cluster mean,normalized */ (void)sprintf(ens,"dsdn"); break; default: (void)sprintf(ens,"none"); } } else (void)sprintf(ens,"none"); /* if Product Definition Template = 4.8, then add the following to the forecast hour */ /* Takes into account accumulations, such as precipitation */ if (templateNum == 8) { TimeUnitIndicator=Template[25]; ForecastTime=Template[26]; /* possibility that these won't add up properly if different units - save for later */ rc = M0GetRealForecastTime(TimeUnitIndicator,ForecastTime,&FHOUR); *fhour += FHOUR; } rc = M0Grib2GetLevelInfo(FirstFixedSfcType,FirstFixedSfc,FirstFixedSfcScale, &Level1,&Level1Scale,&LUnit1); rc = M0Grib2GetLevelInfo(SecondFixedSfcType,SecondFixedSfc,SecondFixedSfcScale, &Level2,&Level2Scale,&LUnit2); rc = grb2ParmLookup(n_gb2parm,parmList,Discipline,ParameterCategory,ParameterNumber, &Parameter,&Parameter4,&Unit,&Unit4); if (rc < 0) return(rc); /*rc = M0Grib2GetParameterString (ParameterCategory, ParameterNumber, &Parameter,&Parameter4,&Unit,&Unit4); */ *Pstring = Parameter; M0sxtrce(gribdbg); *Pstring4 = lit_(Parameter4,4); *Ustring = Unit; *Ustring4 = lit_(Unit4,4); *Lev1 = Level1; *Lev2 = Level2; *Lev1Type = FirstFixedSfcType; *Lev2Type = SecondFixedSfcType; *LevUnit = LUnit1; *LevScale = Level1Scale; /* <<<<< UPC mod 20080803 - use memcpy to move bytes into iModelName >>>>> */ memcpy( iModelName, Model, 4 ); *ensembleString = lit_(ens,4); return(0); } /* *$ Name: *$ McIntLon - converts longitude to McIDAS standards *$ *$ Interface: *$ integer function *$ McIntLon ( float Lon ) *$ *$ Input: *$ Lon - longitude *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ n - integer that is lon*10000, where -180 <= lon <= 180. *$ *$ Remarks: *$ Converts longitudes to +/- 180 degrees, and returns the scaled *$ value appropriate for the grid header (that is, *10000) *$ *$ Categories: *$ utility */ int McIntLon(float Lon) /* convert a longitude to +/-180, and scale by 10000 ** for the grid header */ { while (Lon < -180.) Lon += 360.; while (Lon > 180.) Lon -= 360.; return ( (int) (Lon*10000) ); } /* *$ Name: *$ M0IsGoodPosNum - is the position number valid *$ *$ Interface: *$ integer function M0IsGoodPosNum(integer GribPositionNumber, *$ integer bpos, integer epos) *$ *$ Input: *$ GribPositionNumber - position number of this grib file *$ bpos - valid beginning position number *$ epos - valid ending position number *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - not a valid position number *$ 1 - is a valid position number *$ *$ Remarks: *$ See if position number matches. If bpos=0, all positions match *$ *$ Categories: *$ utility */ int M0IsGoodPosNum(int GribPositionNumber, int bpos, int epos) { (void)sprintf(gribdbg,"bpos: %d epos: %d test: %d ",bpos,epos,GribPositionNumber); M0sxtrce(gribdbg); if (bpos == 0) return(1); if (bpos != 0) { if (GribPositionNumber >= bpos && GribPositionNumber <= epos) { M0sxtrce("position is valid"); return(1); } } return(0); } /* *$ Name: *$ M0GribCheckSpecialCase - does the grid match the request for *$ special levels? the request for *$ *$ Interface: *$ integer function M0GribCheckSpecialCase(char * RequestString, *$ integer GridHeaderLevel) *$ *$ Input: *$ RequestString - level requested on command line *$ GridHeaderLevel - slot #9 from the grid header *$ *$ Input and Output: *$ none *$ *$ Output: *$ none *$ *$ Return values: *$ 0 - does not match *$ 1 - matches *$ *$ Remarks: *$ See if levels match. Return 1 if they do. *$ *$ Categories: *$ utility */ int M0GribCheckSpecialCase(char * RequestString, int GridHeaderLev) { int match = 0; /* assume no match */ int i,j; /* loop bounds */ int TestGridInt; char TestGridLev[5]; char TestRequestString[5]; memset(&TestGridLev[0],0,(size_t)5); memset(&TestRequestString[0],0,(size_t)5); memcpy(&TestGridInt,RequestString,(size_t)4); memcpy(&TestGridLev[0],&GridHeaderLev,(size_t)4); strcpy(&TestRequestString[0],RequestString); TestGridLev[4] = (char)0; for (i = 0; i < 4; i++) { if (TestRequestString[i] == 0 && i < 4) { /* right pad with blanks */ for (j = i ; j < 4 ; j++) { TestRequestString[j] = (char)32; } TestRequestString[4] = 0; break; } } M0sxtrce("SPECIAL CASE!"); (void)sprintf(gribdbg,"SPECIAL CASE! >%s< %d >%d< >%s< %d %x ", RequestString,TestGridInt,GridHeaderLev,TestGridLev, strcmp(RequestString,TestGridLev),strstr(RequestString,TestGridLev)); M0sxtrce(gribdbg); /* Some McIDAS grid header level values are special codes */ if ( (strcmp(RequestString,"SFC") == 0 && GridHeaderLev == 1001) || (strcmp(RequestString,"MSL") == 0 && GridHeaderLev == 1013) || (strcmp(RequestString,"TRO") == 0 && GridHeaderLev == 0) || (strcmp(RequestString,"") == 0 && GridHeaderLev == 999) ) match = 1; if (TestGridInt == GridHeaderLev) match = 1; if (strcmp(RequestString,TestGridLev) == 0) match = 1; if (strcmp(TestRequestString,TestGridLev) == 0) match = 1; return(match); }