1 #include <stdlib.h>
2 #include "grib2.h"
3 #include "pdstemplates.h"
4 
5 
6 static const struct pdstemplate templatespds[MAXPDSTEMP] = {
7              // 4.0: Analysis or Forecast at Horizontal Level/Layer
8              //      at a point in time
9          {0,15,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4} },
10              // 4.1: Individual Ensemble Forecast at Horizontal Level/Layer
11              //      at a point in time
12          {1,18,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1} },
13              // 4.2: Derived Fcst based on whole Ensemble at Horiz Level/Layer
14              //      at a point in time
15          {2,17,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1} },
16              // 4.3: Derived Fcst based on Ensemble cluster over rectangular
17              //      area at Horiz Level/Layer at a point in time
18          {3,31,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,1,1,1,1,-4,-4,4,4,1,-1,4,-1,4} },
19              // 4.4: Derived Fcst based on Ensemble cluster over circular
20              //      area at Horiz Level/Layer at a point in time
21          {4,30,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,1,1,1,1,-4,4,4,1,-1,4,-1,4} },
22              // 4.5: Probablility Forecast at Horiz Level/Layer
23              //      at a point in time
24          {5,22,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,-1,-4,-1,-4} },
25              // 4.6: Percentile Forecast at Horiz Level/Layer
26              //      at a point in time
27          {6,16,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1} },
28              // 4.7: Analysis or Forecast Error at Horizontal Level/Layer
29              //      at a point in time
30          {7,15,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4} },
31              // 4.8: Ave/Accum/etc... at Horiz Level/Layer
32              //      in a time interval
33          {8,29,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
34              // 4.9: Probablility Forecast at Horiz Level/Layer
35              //      in a time interval
36          {9,36,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,-1,-4,-1,-4,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
37              // 4.10: Percentile Forecast at Horiz Level/Layer
38              //       in a time interval
39          {10,30,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
40              // 4.11: Individual Ensemble Forecast at Horizontal Level/Layer
41              //       in a time interval
42          {11,32,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
43              // 4.12: Derived Fcst based on whole Ensemble at Horiz Level/Layer
44              //       in a time interval
45          {12,31,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
46              // 4.13: Derived Fcst based on Ensemble cluster over rectangular
47              //       area at Horiz Level/Layer in a time interval
48          {13,45,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,1,1,1,1,-4,-4,4,4,1,-1,4,-1,4,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
49              // 4.14: Derived Fcst based on Ensemble cluster over circular
50              //       area at Horiz Level/Layer in a time interval
51          {14,44,1, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,1,1,1,1,1,1,1,-4,4,4,1,-1,4,-1,4,2,1,1,1,1,1,1,4,1,1,1,4,1,4} },
52              // 4.20: Radar Product
53          {20,19,0, {1,1,1,1,1,-4,4,2,4,2,1,1,1,1,1,2,1,3,2} },
54              // 4.30: Satellite Product
55          {30,5,1, {1,1,1,1,1} },
56              // 4.254: CCITT IA5 Character String
57          {254,3,0, {1,1,4} },
58              // 4.1000: Cross section of analysis or forecast
59              //         at a point in time
60          {1000,9,0, {1,1,1,1,1,2,1,1,4} },
61              // 4.1001: Cross section of Ave/Accum/etc... analysis or forecast
62              //         in a time interval
63          {1001,16,0, {1,1,1,1,1,2,1,1,4,4,1,1,1,4,1,4} },
64              // 4.1001: Cross section of Ave/Accum/etc... analysis or forecast
65              //         over latitude or longitude
66          {1002,15,0, {1,1,1,1,1,2,1,1,4,1,1,1,4,4,2} },
67              // 4.1100: Hovmoller-type grid w/ no averaging or other
68              //         statistical processing
69          {1100,15,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4} },
70              // 4.1100: Hovmoller-type grid with averaging or other
71              //         statistical processing
72          {1101,22,0, {1,1,1,1,1,2,1,1,4,1,-1,-4,1,-1,-4,4,1,1,1,4,1,4} }
73 
74       } ;
75 
get_templatespds()76 const struct pdstemplate *get_templatespds()
77 {
78     return templatespds;
79 }
80 
getpdsindex(g2int number)81 g2int getpdsindex(g2int number)
82 ///$$$  SUBPROGRAM DOCUMENTATION BLOCK
83 //                .      .    .                                       .
84 // SUBPROGRAM:    getpdsindex
85 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2001-06-28
86 //
87 // ABSTRACT: This function returns the index of specified Product
88 //   Definition Template 4.NN (NN=number) in array templates.
89 //
90 // PROGRAM HISTORY LOG:
91 // 2001-06-28  Gilbert
92 //
93 // USAGE:    index=getpdsindex(number)
94 //   INPUT ARGUMENT LIST:
95 //     number   - NN, indicating the number of the Product Definition
96 //                Template 4.NN that is being requested.
97 //
98 // RETURNS:  Index of PDT 4.NN in array templates, if template exists.
99 //           = -1, otherwise.
100 //
101 // REMARKS: None
102 //
103 // ATTRIBUTES:
104 //   LANGUAGE: C
105 //   MACHINE:  IBM SP
106 //
107 //$$$/
108 {
109            g2int j,getpdsindex=-1;
110 
111            for (j=0;j<MAXPDSTEMP;j++) {
112               if (number == templatespds[j].template_num) {
113                  getpdsindex=j;
114                  return(getpdsindex);
115               }
116            }
117 
118            return(getpdsindex);
119 }
120 
121 
getpdstemplate(g2int number)122 xxtemplate *getpdstemplate(g2int number)
123 ///$$$  SUBPROGRAM DOCUMENTATION BLOCK
124 //                .      .    .                                       .
125 // SUBPROGRAM:    getpdstemplate
126 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-11
127 //
128 // ABSTRACT: This subroutine returns PDS template information for a
129 //   specified Product Definition Template 4.NN.
130 //   The number of entries in the template is returned along with a map
131 //   of the number of octets occupied by each entry.  Also, a flag is
132 //   returned to indicate whether the template would need to be extended.
133 //
134 // PROGRAM HISTORY LOG:
135 // 2000-05-11  Gilbert
136 //
137 // USAGE:    CALL getpdstemplate(number)
138 //   INPUT ARGUMENT LIST:
139 //     number   - NN, indicating the number of the Product Definition
140 //                Template 4.NN that is being requested.
141 //
142 //   RETURN VALUE:
143 //        - Pointer to the returned template struct.
144 //          Returns NULL pointer, if template not found.
145 //
146 // REMARKS: None
147 //
148 // ATTRIBUTES:
149 //   LANGUAGE: C
150 //   MACHINE:  IBM SP
151 //
152 //$$$/
153 {
154            g2int index;
155            xxtemplate *new;
156 
157            index=getpdsindex(number);
158 
159            if (index != -1) {
160               new=(xxtemplate *)malloc(sizeof(xxtemplate));
161               new->type=4;
162               new->num=templatespds[index].template_num;
163               new->maplen=templatespds[index].mappdslen;
164               new->needext=templatespds[index].needext;
165               new->map=(g2int *)templatespds[index].mappds;
166               new->extlen=0;
167               new->ext=0;        //NULL
168               return(new);
169            }
170            else {
171              printf("getpdstemplate: PDS Template 4.%d not defined.\n",(int)number);
172              return(0);        //NULL
173            }
174 
175          return(0);        //NULL
176 }
177 
178 
extpdstemplate(g2int number,g2int * list)179 xxtemplate *extpdstemplate(g2int number,g2int *list)
180 ///$$$  SUBPROGRAM DOCUMENTATION BLOCK
181 //                .      .    .                                       .
182 // SUBPROGRAM:    extpdstemplate
183 //   PRGMMR: Gilbert         ORG: W/NP11    DATE: 2000-05-11
184 //
185 // ABSTRACT: This subroutine generates the remaining octet map for a
186 //   given Product Definition Template, if required.  Some Templates can
187 //   vary depending on data values given in an earlier part of the
188 //   Template, and it is necessary to know some of the earlier entry
189 //   values to generate the full octet map of the Template.
190 //
191 // PROGRAM HISTORY LOG:
192 // 2000-05-11  Gilbert
193 //
194 // USAGE:    CALL extpdstemplate(number,list)
195 //   INPUT ARGUMENT LIST:
196 //     number   - NN, indicating the number of the Product Definition
197 //                Template 4.NN that is being requested.
198 //     list()   - The list of values for each entry in the
199 //                the Product Definition Template 4.NN.
200 //
201 //   RETURN VALUE:
202 //        - Pointer to the returned template struct.
203 //          Returns NULL pointer, if template not found.
204 //
205 // ATTRIBUTES:
206 //   LANGUAGE: C
207 //   MACHINE:  IBM SP
208 //
209 //$$$
210 {
211            xxtemplate *new;
212            g2int index,i,j,k,l;
213 
214            index=getpdsindex(number);
215            if (index == -1) return(0);
216 
217            new=getpdstemplate(number);
218 
219            if ( ! new->needext ) return(new);
220 
221            if ( number == 3 ) {
222               new->extlen=list[26];
223               new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
224               for (i=0;i<new->extlen;i++) {
225                  new->ext[i]=1;
226               }
227            }
228            else if ( number == 4 ) {
229               new->extlen=list[25];
230               new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
231               for (i=0;i<new->extlen;i++) {
232                  new->ext[i]=1;
233               }
234            }
235            else if ( number == 8 ) {
236               if ( list[21] > 1 ) {
237                  new->extlen=(list[21]-1)*6;
238                  new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
239                  for (j=2;j<=list[21];j++) {
240                     l=(j-2)*6;
241                     for (k=0;k<6;k++) {
242                        new->ext[l+k]=new->map[23+k];
243                     }
244                  }
245               }
246            }
247            else if ( number == 9 ) {
248               if ( list[28] > 1 ) {
249                  new->extlen=(list[28]-1)*6;
250                  new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
251                  for (j=2;j<=list[28];j++) {
252                     l=(j-2)*6;
253                     for (k=0;k<6;k++) {
254                        new->ext[l+k]=new->map[30+k];
255                     }
256                  }
257               }
258            }
259            else if ( number == 10 ) {
260               if ( list[22] > 1 ) {
261                  new->extlen=(list[22]-1)*6;
262                  new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
263                  for (j=2;j<=list[22];j++) {
264                     l=(j-2)*6;
265                     for (k=0;k<6;k++) {
266                        new->ext[l+k]=new->map[24+k];
267                     }
268                  }
269               }
270            }
271            else if ( number == 11 ) {
272               if ( list[24] > 1 ) {
273                  new->extlen=(list[24]-1)*6;
274                  new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
275                  for (j=2;j<=list[24];j++) {
276                     l=(j-2)*6;
277                     for (k=0;k<6;k++) {
278                        new->ext[l+k]=new->map[26+k];
279                     }
280                  }
281               }
282            }
283            else if ( number == 12 ) {
284               if ( list[23] > 1 ) {
285                  new->extlen=(list[23]-1)*6;
286                  new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
287                  for (j=2;j<=list[23];j++) {
288                     l=(j-2)*6;
289                     for (k=0;k<6;k++) {
290                        new->ext[l+k]=new->map[25+k];
291                     }
292                  }
293               }
294            }
295            else if ( number == 13 ) {
296               new->extlen=((list[37]-1)*6)+list[26];
297               new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
298               if ( list[37] > 1 ) {
299                  for (j=2;j<=list[37];j++) {
300                     l=(j-2)*6;
301                     for (k=0;k<6;k++) {
302                        new->ext[l+k]=new->map[39+k];
303                     }
304                  }
305               }
306               l=(list[37]-1)*6;
307               if ( l<0 ) l=0;
308               for (i=0;i<list[26];i++) {
309                 new->ext[l+i]=1;
310               }
311            }
312            else if ( number == 14 ) {
313               new->extlen=((list[36]-1)*6)+list[25];
314               new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
315               if ( list[36] > 1 ) {
316                  for (j=2;j<=list[36];j++) {
317                     l=(j-2)*6;
318                     for (k=0;k<6;k++) {
319                        new->ext[l+k]=new->map[38+k];
320                     }
321                  }
322               }
323               l=(list[36]-1)*6;
324               if ( l<0 ) l=0;
325               for (i=0;i<list[25];i++) {
326                 new->ext[l+i]=1;
327               }
328            }
329            else if ( number == 30 ) {
330               new->extlen=list[4]*5;
331               new->ext=(g2int *)malloc(sizeof(g2int)*new->extlen);
332               for (i=0;i<list[4];i++) {
333                  l=i*5;
334                  new->ext[l]=2;
335                  new->ext[l+1]=2;
336                  new->ext[l+2]=1;
337                  new->ext[l+3]=1;
338                  new->ext[l+4]=4;
339               }
340            }
341            return(new);
342 
343 }
344 
345