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