varscan.c 39.6 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
2
3
4
#if defined (HAVE_CONFIG_H)
#  include "config.h"
#endif

5
#include <stdbool.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
7
8
9
#include <string.h>
#include <math.h>

#include "cdi.h"
10
#include "cdi_int.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
11
#include "dmemory.h"
12
#include "resource_handle.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
13
14
#include "varscan.h"
#include "vlist.h"
15
#include "grid.h"
16
#include "zaxis.h"
17
#include "subtype.h"
18
19


Uwe Schulzweida's avatar
Uwe Schulzweida committed
20
21
22
23
24
25
#undef  UNDEFID
#define UNDEFID -1

static size_t Vctsize = 0;
static double *Vct = NULL;

26
27
static int numberOfVerticalLevels = 0;
static int numberOfVerticalGrid = 0;
28
static unsigned char uuidVGrid[CDI_UUID_SIZE];
29

30

Uwe Schulzweida's avatar
Uwe Schulzweida committed
31
32
33
34
35
36
37
typedef struct
{
  int      level1;
  int      level2;
  int      recID;
  int      lindex;
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
38
leveltable_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
39

40

Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
typedef struct
{
43
44
  int           subtypeIndex; /* corresponding tile in subtype_t structure (subtype->self) */

45
  unsigned      nlevels;
46
  int           levelTableSize;
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  leveltable_t* levelTable;
} subtypetable_t;


typedef struct
{
  int            param;
  int            prec;
  int            tsteptype;
  int            timave;
  int            timaccu;
  int            gridID;
  int            zaxistype;
  int            ltype1;     /* GRIB first level type */
  int            ltype2;     /* GRIB second level type */
  int            lbounds;
  int            level_sf;
  int            level_unit;
  int            zaxisID;

  int            nsubtypes_alloc;
  int            nsubtypes;
  subtypetable_t *recordTable;    /* ~ two-dimensional record list [nsubtypes_alloc][levelTableSize] */

  int            instID;
  int            modelID;
  int            tableID;
  int            comptype;       // compression type
  int            complevel;      // compression level
  int            lmissval;
  double         missval;
  char          *name;
  char          *stdname;
  char          *longname;
  char          *units;
  ensinfo_t     *ensdata;
  int            typeOfGeneratingProcess;
  int            productDefinitionTemplate;

  /* meta-data for specification of tiles (currently only GRIB-API: */
87
  subtype_t     *tiles;
88

89
90
91
  int                 opt_grib_nentries;                       /* current no. key-value pairs            */
  int                 opt_grib_kvpair_size;                    /* current allocated size                 */
  opt_key_val_pair_t *opt_grib_kvpair;                         /* (optional) list of keyword/value pairs */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
92
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
vartable_t;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
94

95

96
static vartable_t *vartable;
97
98
static unsigned varTablesize = 0;
static unsigned nvars = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99

100

101
102
static void
paramInitEntry(unsigned varID, int param)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
103
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104
  vartable[varID].param          = param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
105
  vartable[varID].prec           = 0;
106
  vartable[varID].tsteptype      = TSTEP_INSTANT;
107
108
  vartable[varID].timave         = 0;
  vartable[varID].timaccu        = 0;
109
110
  vartable[varID].gridID         = UNDEFID;
  vartable[varID].zaxistype      = 0;
111
112
  vartable[varID].ltype1         = 0;
  vartable[varID].ltype2         = -1;
113
114
  vartable[varID].lbounds        = 0;
  vartable[varID].level_sf       = 0;
115
  vartable[varID].level_unit     = 0;
116
117
118
  vartable[varID].recordTable    = NULL;
  vartable[varID].nsubtypes_alloc= 0;
  vartable[varID].nsubtypes      = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
119
120
121
  vartable[varID].instID         = UNDEFID;
  vartable[varID].modelID        = UNDEFID;
  vartable[varID].tableID        = UNDEFID;
122
123
  vartable[varID].typeOfGeneratingProcess   = UNDEFID;
  vartable[varID].productDefinitionTemplate = UNDEFID;
124
  vartable[varID].comptype       = COMPRESS_NONE;
125
  vartable[varID].complevel      = 1;
126
127
  vartable[varID].lmissval       = 0;
  vartable[varID].missval        = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
128
  vartable[varID].name           = NULL;
129
  vartable[varID].stdname        = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
130
131
  vartable[varID].longname       = NULL;
  vartable[varID].units          = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
132
  vartable[varID].ensdata        = NULL;
133
  vartable[varID].tiles          = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
134
135
}

136
137
/* Test if a variable specified by the given meta-data has already
 * been registered in "vartable". */
138
static unsigned
139
varGetEntry(int param, int zaxistype, int ltype1, int tsteptype, const char *name, const var_tile_t *tiles)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
140
{
141
  for ( unsigned varID = 0; varID < varTablesize; varID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
142
    {
143
144
145
      /* testing for "param" implicitly checks if we are beyond the
       * current vartable size: */
      if (vartable[varID].param == param)
146
        {
147
148
149
150
151
152
          int no_of_tiles = -1;
          if ( tiles ) no_of_tiles = tiles->numberOfTiles;
          int vt_no_of_tiles = -1;
          if ( vartable[varID].tiles )
            vt_no_of_tiles = subtypeGetGlobalDataP(vartable[varID].tiles,
                                                   SUBTYPE_ATT_NUMBER_OF_TILES);
153
154
155
          if ( (vartable[varID].zaxistype  == zaxistype)               &&
               (vartable[varID].ltype1     == ltype1   )               &&
               (vartable[varID].tsteptype  == tsteptype)               &&
156
               (vt_no_of_tiles == no_of_tiles) )
157
            {
158
159
160
161
162
163
164
165
              if ( name && name[0] && vartable[varID].name && vartable[varID].name[0] )
                {
                  if ( strcmp(name, vartable[varID].name) == 0 ) return (varID);
                }
              else
                {
                  return (varID);
                }
166
167
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
168
169
    }

170
  return (unsigned)-1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
171
172
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
174
175
void varFree(void)
{
176
177
  if ( CDI_Debug ) Message("call to varFree");

178
  for ( unsigned varID = 0; varID < nvars; varID++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
179
    {
180
181
182
183
184
185
      if ( vartable[varID].recordTable )
        {
          for (int isub=0; isub<vartable[varID].nsubtypes_alloc; isub++)
            free(vartable[varID].recordTable[isub].levelTable);
          free(vartable[varID].recordTable);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
186
187

      if ( vartable[varID].name )     free(vartable[varID].name);
188
      if ( vartable[varID].stdname )  free(vartable[varID].stdname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
189
190
      if ( vartable[varID].longname ) free(vartable[varID].longname);
      if ( vartable[varID].units )    free(vartable[varID].units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
191
      if ( vartable[varID].ensdata )  free(vartable[varID].ensdata);
192
      if ( vartable[varID].tiles )    subtypeDestroyPtr(vartable[varID].tiles);
193

194
      if ( vartable[varID].opt_grib_kvpair )
195
196
197
198
199
200
201
        {
          for (int i=0; i<vartable[varID].opt_grib_nentries; i++) {
            if ( vartable[varID].opt_grib_kvpair[i].keyword )
              free(vartable[varID].opt_grib_kvpair[i].keyword);
          }
          free(vartable[varID].opt_grib_kvpair);
        }
202
203
204
      vartable[varID].opt_grib_nentries    = 0;
      vartable[varID].opt_grib_kvpair_size = 0;
      vartable[varID].opt_grib_kvpair      = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    }

  if ( vartable )
    free(vartable);

  vartable = NULL;
  varTablesize = 0;
  nvars = 0;

  if ( Vct )
    free(Vct);

  Vct = NULL;
  Vctsize = 0;
}

221
/* Search for a tile subtype with subtypeIndex == tile_index. */
222
static int tileGetEntry(unsigned varID, int tile_index)
223
224
225
226
227
228
229
230
231
{
  for (int isub=0; isub<vartable[varID].nsubtypes; isub++)
    if (vartable[varID].recordTable[isub].subtypeIndex == tile_index)
      return isub;
  return CDI_UNDEFID;
}


/* Resizes vartable:recordTable data structure, if necessary. */
232
static int tileNewEntry(int varID)
233
234
235
236
237
{
  int tileID = 0;
  if (vartable[varID].nsubtypes_alloc == 0)
    {
      /* create table for the first time. */
238
      vartable[varID].nsubtypes_alloc = 2;
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
      vartable[varID].nsubtypes       = 0;
      vartable[varID].recordTable     =
        (subtypetable_t *)xmalloc((size_t)vartable[varID].nsubtypes_alloc * sizeof (subtypetable_t));
      if( vartable[varID].recordTable == NULL )
        SysError("Allocation of leveltable failed!");

      for (int isub = 0; isub<vartable[varID].nsubtypes_alloc; isub++) {
	vartable[varID].recordTable[isub].levelTable     = NULL;
        vartable[varID].recordTable[isub].levelTableSize = 0;
        vartable[varID].recordTable[isub].nlevels        = 0;
        vartable[varID].recordTable[isub].subtypeIndex   = CDI_UNDEFID;
      }
    }
  else
    {
      /* data structure large enough; find a free entry. */
      while(tileID <  vartable[varID].nsubtypes_alloc)
	{
	  if (vartable[varID].recordTable[tileID].levelTable == NULL) break;
	  tileID++;
	}
    }

  /* If the table overflows, double its size. */
  if (tileID == vartable[varID].nsubtypes_alloc)
    {
      tileID = vartable[varID].nsubtypes_alloc;
      vartable[varID].nsubtypes_alloc *= 2;
      vartable[varID].recordTable   =
        (subtypetable_t *)xrealloc(vartable[varID].recordTable,
                                   (size_t)vartable[varID].nsubtypes_alloc * sizeof (subtypetable_t));
      if (vartable[varID].recordTable == NULL)
        SysError("Reallocation of leveltable failed");
      for(int isub=tileID; isub<vartable[varID].nsubtypes_alloc; isub++) {
	vartable[varID].recordTable[isub].levelTable     = NULL;
        vartable[varID].recordTable[isub].levelTableSize = 0;
        vartable[varID].recordTable[isub].nlevels        = 0;
        vartable[varID].recordTable[isub].subtypeIndex   = CDI_UNDEFID;
      }
    }

  return tileID;
}


284
static int levelNewEntry(unsigned varID, int level1, int level2, int tileID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
285
286
287
{
  int levelID = 0;
  int levelTableSize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
288
  leveltable_t *levelTable;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
289

290
291
  levelTableSize = vartable[varID].recordTable[tileID].levelTableSize;
  levelTable     = vartable[varID].recordTable[tileID].levelTable;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
292
293
294
295
296
297
298
299
300
301

  /*
    Look for a free slot in levelTable.
    (Create the table the first time through).
  */
  if ( ! levelTableSize )
    {
      int i;

      levelTableSize = 2;
302
303
      levelTable = (leveltable_t *)xmalloc((size_t)levelTableSize
                                           * sizeof (leveltable_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304
305
      if( levelTable == NULL )
	{
306
307
          Message("levelTableSize = %d", levelTableSize);
	  SysError("Allocation of leveltable failed!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
309
310
	}

      for( i = 0; i < levelTableSize; i++ )
311
        levelTable[i].recID = UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
    }
  else
    {
      while( levelID < levelTableSize )
	{
	  if ( levelTable[levelID].recID == UNDEFID ) break;
	  levelID++;
	}
    }
  /*
    If the table overflows, double its size.
  */
  if( levelID == levelTableSize )
    {
      int i;

      levelTableSize = 2*levelTableSize;
329
330
      levelTable = (leveltable_t *)xrealloc(levelTable, (size_t)levelTableSize
                                            * sizeof (leveltable_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
331
332
      if( levelTable == NULL )
	{
333
334
          Message("levelTableSize = %d", levelTableSize);
	  SysError("Reallocation of leveltable failed");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
335
336
337
338
	}
      levelID = levelTableSize/2;

      for( i = levelID; i < levelTableSize; i++ )
339
        levelTable[i].recID = UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
340
341
    }

342
343
344
  levelTable[levelID].level1   = level1;
  levelTable[levelID].level2   = level2;
  levelTable[levelID].lindex   = levelID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
345

346
347
348
  vartable[varID].recordTable[tileID].nlevels        = (unsigned)levelID+1;
  vartable[varID].recordTable[tileID].levelTableSize = levelTableSize;
  vartable[varID].recordTable[tileID].levelTable     = levelTable;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
349
350
351
352

  return (levelID);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
353
#define  UNDEF_PARAM  -4711
Uwe Schulzweida's avatar
Uwe Schulzweida committed
354

355
356
static unsigned
paramNewEntry(int param)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
357
{
358
  unsigned varID = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
360
361
362
363
364
365
366

  /*
    Look for a free slot in vartable.
    (Create the table the first time through).
  */
  if ( ! varTablesize )
    {
      varTablesize = 2;
367
368
      vartable = (vartable_t *)xmalloc((size_t)varTablesize
                                       * sizeof (vartable_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369
370
      if( vartable == NULL )
	{
371
372
          Message("varTablesize = %d", varTablesize);
	  SysError("Allocation of vartable failed");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
374
	}

375
      for( unsigned i = 0; i < varTablesize; i++ )
376
377
        {
          vartable[i].param = UNDEF_PARAM;
378
          vartable[i].opt_grib_kvpair      = NULL;
379
          vartable[i].opt_grib_kvpair_size = 0;
380
          vartable[i].opt_grib_nentries    = 0;
381
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
382
383
384
385
386
    }
  else
    {
      while( varID < varTablesize )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
387
	  if ( vartable[varID].param == UNDEF_PARAM ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
389
390
391
392
393
	  varID++;
	}
    }
  /*
    If the table overflows, double its size.
  */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
394
  if ( varID == varTablesize )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
396
    {

397
398
399
      varTablesize = 2 * varTablesize;
      vartable = (vartable_t *)xrealloc(vartable, (size_t)varTablesize
                                        * sizeof (vartable_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
400
401
      if( vartable == NULL )
	{
402
403
          Message("varTablesize = %d", varTablesize);
	  SysError("Reallocation of vartable failed!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
405
406
	}
      varID = varTablesize/2;

407
      for( unsigned i = varID; i < varTablesize; i++ )
408
409
        {
          vartable[i].param = UNDEF_PARAM;
410
          vartable[i].opt_grib_kvpair      = NULL;
411
          vartable[i].opt_grib_kvpair_size = 0;
412
          vartable[i].opt_grib_nentries    = 0;
413
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
414
415
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
416
  paramInitEntry(varID, param);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
417
418
419
420
421

  return (varID);
}


422
423
/* Append tile set to a subtype. Return index of the new tile (i.e.
 * the "entry->self" value). */
424
425
static
int varInsertTileSubtype(vartable_t *vptr, const var_tile_t *tiles)
426
{
427
428
  if ( tiles == NULL ) return -1;

429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
  int totalno_of_tileattr_pairs = -1;
  int tileClassification = -1;
  int numberOfTiles = -1;
  int numberOfAttributes = -1;
  int tileindex = -1;
  int attribute = -1;

  if ( tiles )
    {
      totalno_of_tileattr_pairs = tiles->totalno_of_tileattr_pairs;
      tileClassification =  tiles->tileClassification;
      numberOfTiles = tiles->numberOfTiles;
      numberOfAttributes = tiles->numberOfAttributes;
      tileindex = tiles->tileindex;
      attribute = tiles->attribute;
    }

446
447
448
449
  /* first, generate a subtype based on the info in "tiles". */

  subtype_t *subtype_ptr;
  subtypeAllocate(&subtype_ptr, SUBTYPE_TILES);
450
451
452
  subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TOTALNO_OF_TILEATTR_PAIRS, totalno_of_tileattr_pairs);
  subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_TILE_CLASSIFICATION      , tileClassification);
  subtypeDefGlobalDataP(subtype_ptr, SUBTYPE_ATT_NUMBER_OF_TILES          , numberOfTiles);
453

454
  /*
455
   * Here, we create a tile set for comparison that contains only one
456
   * tile/attribute pair (based on "tiles").
457
458
   */
  struct subtype_entry_t *entry = subtypeEntryInsert(subtype_ptr);
459
460
461
  subtypeDefEntryDataP(entry, SUBTYPE_ATT_NUMBER_OF_ATTR,            numberOfAttributes);
  subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEINDEX,                 tileindex);
  subtypeDefEntryDataP(entry, SUBTYPE_ATT_TILEATTRIBUTE,             attribute);
462
463
464
465
466
467
468
469
470
471
472
473
474
475

  if (vptr->tiles == NULL) {
    vptr->tiles = subtype_ptr;
    return 0;
  }
  else {
    tilesetInsertP(vptr->tiles, subtype_ptr);
    subtypeDestroyPtr(subtype_ptr);
    return vptr->tiles->nentries - 1;
  }
  return CDI_UNDEFID;
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
void varAddRecord(int recID, int param, int gridID, int zaxistype, int lbounds,
477
		  int level1, int level2, int level_sf, int level_unit, int prec,
478
		  int *pvarID, int *plevelID, int tsteptype, int numavg, int ltype1, int ltype2,
479
		  const char *name, const char *stdname, const char *longname, const char *units,
480
                  const var_tile_t *tiles, int *tile_index)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
481
{
482
  unsigned varID = (cdiSplitLtype105 != 1 || zaxistype != ZAXIS_HEIGHT) ?
483
    varGetEntry(param, zaxistype, ltype1, tsteptype, name, tiles) : (unsigned)UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484

485
  if ( varID == (unsigned)UNDEFID )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
486
487
    {
      nvars++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
      varID = paramNewEntry(param);
489
490
      vartable[varID].gridID     = gridID;
      vartable[varID].zaxistype  = zaxistype;
491
492
      vartable[varID].ltype1     = ltype1;
      vartable[varID].ltype2     = ltype2;
493
494
      vartable[varID].lbounds    = lbounds;
      vartable[varID].level_sf   = level_sf;
495
      vartable[varID].level_unit = level_unit;
496
      vartable[varID].tsteptype  = tsteptype;
497

498
      if ( numavg ) vartable[varID].timave = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
500

      if ( name )     if ( name[0] )     vartable[varID].name     = strdup(name);
501
      if ( stdname )  if ( stdname[0] )  vartable[varID].stdname  = strdup(stdname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
502
503
      if ( longname ) if ( longname[0] ) vartable[varID].longname = strdup(longname);
      if ( units )    if ( units[0] )    vartable[varID].units    = strdup(units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504
505
506
    }
  else
    {
507
508
509
      char paramstr[32];
      cdiParamToString(param, paramstr, sizeof(paramstr));

Uwe Schulzweida's avatar
Uwe Schulzweida committed
510
511
      if ( vartable[varID].gridID != gridID )
	{
512
	  Message("param = %s gridID = %d", paramstr, gridID);
513
	  Error("horizontal grid must not change for same parameter!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514
	}
515
      if ( vartable[varID].zaxistype != zaxistype )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
	{
517
	  Message("param = %s zaxistype = %d", paramstr, zaxistype);
518
	  Error("zaxistype must not change for same parameter!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519
520
521
	}
    }

522
523
  if ( prec > vartable[varID].prec ) vartable[varID].prec = prec;

524
525
  /* append current tile to tile subtype info. */
  int this_tile = varInsertTileSubtype(&vartable[varID], tiles);
526
527
  int tileID = tileGetEntry(varID, this_tile);
  if ( tile_index ) (*tile_index) = this_tile;
528
  if (tileID == CDI_UNDEFID) {
Thomas Jahns's avatar
Thomas Jahns committed
529
    tileID = tileNewEntry((int)varID);
530
531
532
533
534
    vartable[varID].recordTable[tileID].subtypeIndex = this_tile;
    vartable[varID].nsubtypes++;
  }

  /* append current level to level table info */
535
  int levelID = levelNewEntry(varID, level1, level2, tileID);
536
  if (CDI_Debug)
537
    Message("vartable[%d].recordTable[%d].levelTable[%d].recID = %d; level1,2=%d,%d",
538
            varID, tileID, levelID, recID, level1, level2);
539
  vartable[varID].recordTable[tileID].levelTable[levelID].recID = recID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
540

541
  *pvarID   = (int) varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
543
  *plevelID = levelID;
}
544
545


Uwe Schulzweida's avatar
Uwe Schulzweida committed
546
/*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
547
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
548
549
550
551
552
553
554
555
556
int dblcmp(const void *s1, const void *s2)
{
  int cmp = 0;

  if      ( *((double *) s1) < *((double *) s2) ) cmp = -1;
  else if ( *((double *) s1) > *((double *) s2) ) cmp =  1;

  return (cmp);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
557
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
static
559
int cmpLevelTable(const void* s1, const void* s2)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
561
{
  int cmp = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
  const leveltable_t* x = (const leveltable_t*) s1;
  const leveltable_t* y = (const leveltable_t*) s2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
564
565
566
567
568
569
570
571
572
  /*
  printf("%g %g  %d %d\n", x->leve11, y->level1, x, y);
  */
  if      ( x->level1 < y->level1 ) cmp = -1;
  else if ( x->level1 > y->level1 ) cmp =  1;

  return (cmp);
}

573
574
575
576
static
int cmpLevelTableInv(const void* s1, const void* s2)
{
  int cmp = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
577
578
  const leveltable_t* x = (const leveltable_t*) s1;
  const leveltable_t* y = (const leveltable_t*) s2;
579
580
581
582
583
584
585
586
587
  /*
  printf("%g %g  %d %d\n", x->leve11, y->level1, x, y);
  */
  if      ( x->level1 < y->level1 ) cmp =  1;
  else if ( x->level1 > y->level1 ) cmp = -1;

  return (cmp);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
588

589
590
591
592
typedef struct
{
  int      varid;
  int      param;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
593
  int      ltype;
594
595
596
597
598
}
param_t;


static
599
int cmpparam(const void* s1, const void* s2)
600
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601
602
  const param_t* x = (const param_t*) s1;
  const param_t* y = (const param_t*) s2;
603

604
605
  int cmp = (( x->param > y->param ) - ( x->param < y->param )) * 2
           + ( x->ltype > y->ltype ) - ( x->ltype < y->ltype );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
606
607
608
609

  return (cmp);
}

610

611
void cdi_generate_vars(stream_t *streamptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
{
613
  int gridID, zaxisID;
614

Uwe Schulzweida's avatar
Uwe Schulzweida committed
615
  int instID, modelID, tableID;
Thomas Jahns's avatar
Thomas Jahns committed
616
  int param, zaxistype, ltype1, ltype2;
617
  int prec;
618
  int tsteptype;
619
  int timave, timaccu;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
620
  int lbounds;
621
  int comptype;
622
  char name[CDI_MAX_NAME], longname[CDI_MAX_NAME], units[CDI_MAX_NAME];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
624
625
  double *dlevels = NULL;
  double *dlevels1 = NULL;
  double *dlevels2 = NULL;
626
  double level_sf = 1;
627
  int vlistID = streamptr->vlistID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628

629
630
  int *varids = (int *)xmalloc(nvars*sizeof(int));
  for ( unsigned varID = 0; varID < nvars; varID++ ) varids[varID] = (int)varID;
631
632
633

  if ( streamptr->sortname )
    {
634
      param_t *varInfo = (param_t *)xmalloc((size_t)nvars * sizeof (param_t));
635

636
      for ( unsigned varID = 0; varID < nvars; varID++ )
637
	{
638
639
640
	  varInfo[varID].varid = varids[varID];
	  varInfo[varID].param = vartable[varID].param;
	  varInfo[varID].ltype = vartable[varID].ltype1;
641
	}
642
      qsort(varInfo, (size_t)nvars, sizeof(param_t), cmpparam);
643
      for ( unsigned varID = 0; varID < nvars; varID++ )
644
	{
645
	  varids[varID] = varInfo[varID].varid;
646
647
648
649
	}
      free(varInfo);
    }

650
  for ( unsigned index = 0; index < nvars; index++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
    {
652
      int varid      = varids[index];
653

654
655
656
657
      gridID     = vartable[varid].gridID;
      param      = vartable[varid].param;
      ltype1     = vartable[varid].ltype1;
      ltype2     = vartable[varid].ltype2;
658
      zaxistype = vartable[varid].zaxistype;
659
      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && cdiDefaultLeveltype != -1 )
660
	zaxistype = cdiDefaultLeveltype;
661
662
663
664
665
666
667
668
669
      lbounds    = vartable[varid].lbounds;
      prec       = vartable[varid].prec;
      instID     = vartable[varid].instID;
      modelID    = vartable[varid].modelID;
      tableID    = vartable[varid].tableID;
      tsteptype  = vartable[varid].tsteptype;
      timave     = vartable[varid].timave;
      timaccu    = vartable[varid].timaccu;
      comptype   = vartable[varid].comptype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
670

671
      level_sf  = 1;
672
      if ( vartable[varid].level_sf != 0 ) level_sf = 1./vartable[varid].level_sf;
673

Uwe Schulzweida's avatar
Uwe Schulzweida committed
674
675
      zaxisID = UNDEFID;

676
677
678
679
680
      /* consistency check: test if all subtypes have the same levels: */
      unsigned nlevels = vartable[varid].recordTable[0].nlevels;
      for (int isub=1; isub<vartable[varid].nsubtypes; isub++) {
        if (vartable[varid].recordTable[isub].nlevels != nlevels)
          {
681
            fprintf(stderr, "var \"%s\": isub = %d / %d :: "
682
                    "nlevels = %d, vartable[varid].recordTable[isub].nlevels = %d\n",
683
                    vartable[varid].name, isub, vartable[varid].nsubtypes,
684
685
686
687
688
689
                    nlevels, vartable[varid].recordTable[isub].nlevels);
            Error("zaxis size must not change for same parameter!");
          }

        leveltable_t *t1 = vartable[varid].recordTable[isub-1].levelTable;
        leveltable_t *t2 = vartable[varid].recordTable[isub  ].levelTable;
690
        for (unsigned ilev=0; ilev<nlevels; ilev++)
691
692
693
694
          if ((t1[ilev].level1 != t2[ilev].level1)  ||
              (t1[ilev].level2 != t2[ilev].level2)  ||
              (t1[ilev].lindex != t2[ilev].lindex))
            {
695
              fprintf(stderr, "var \"%s\", varID=%d: isub = %d / %d :: "
696
                      "nlevels = %d, vartable[varid].recordTable[isub].nlevels = %d\n",
697
                      vartable[varid].name, varid, isub, vartable[varid].nsubtypes,
698
                      nlevels, vartable[varid].recordTable[isub].nlevels);
699
700
701
              Message("t1[ilev].level1=%d / t2[ilev].level1=%d",t1[ilev].level1, t2[ilev].level1);
              Message("t1[ilev].level2=%d / t2[ilev].level2=%d",t1[ilev].level2, t2[ilev].level2);
              Message("t1[ilev].lindex=%d / t2[ilev].lindex=%d",t1[ilev].lindex, t2[ilev].lindex);
702
703
704
705
706
              Error("zaxis type must not change for same parameter!");
            }
      }
      leveltable_t *levelTable = vartable[varid].recordTable[0].levelTable;

707
      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && nlevels == 1 &&
708
	   levelTable[0].level1 == 0 )
709
	zaxistype = ZAXIS_SURFACE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
711
712

      dlevels = (double *) malloc(nlevels*sizeof(double));

713
      if ( lbounds && zaxistype != ZAXIS_HYBRID && zaxistype != ZAXIS_HYBRID_HALF )
714
	for (unsigned levelID = 0; levelID < nlevels; levelID++ )
715
716
	  dlevels[levelID] = (level_sf*levelTable[levelID].level1 +
	                      level_sf*levelTable[levelID].level2)/2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
      else
718
	for (unsigned levelID = 0; levelID < nlevels; levelID++ )
719
	  dlevels[levelID] = level_sf*levelTable[levelID].level1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
720
721
722

      if ( nlevels > 1 )
	{
723
          bool linc = true, ldec = true, lsort = false;
724
          for (unsigned levelID = 1; levelID < nlevels; levelID++ )
725
726
727
728
729
730
731
732
            {
              /* check increasing of levels */
              linc &= (dlevels[levelID] > dlevels[levelID-1]);
              /* check decreasing of levels */
              ldec &= (dlevels[levelID] < dlevels[levelID-1]);
            }
          /*
           * always sort pressure z-axis to ensure
733
           * levelTable[levelID1].level1 < levelTable[levelID2].level1 <=> levelID1 > levelID2
734
735
736
737
           * unless already sorted in decreasing order
           */
          if ( !ldec && zaxistype == ZAXIS_PRESSURE )
            {
738
              qsort(levelTable, nlevels, sizeof(leveltable_t), cmpLevelTableInv);
739
740
741
742
              lsort = true;
            }
          /*
           * always sort hybrid and depth-below-land z-axis to ensure
743
           * levelTable[levelID1].level1 < levelTable[levelID2].level1 <=> levelID1 < levelID2
744
745
746
747
748
749
           * unless already sorted in increasing order
           */
          else if ( (!linc && !ldec) ||
                    zaxistype == ZAXIS_HYBRID ||
                    zaxistype == ZAXIS_DEPTH_BELOW_LAND )
            {
750
              qsort(levelTable, nlevels, sizeof(leveltable_t), cmpLevelTable);
751
752
              lsort = true;
            }
753
754
755
756

          if ( lsort )
            {
              if ( lbounds && zaxistype != ZAXIS_HYBRID && zaxistype != ZAXIS_HYBRID_HALF )
757
                for (unsigned levelID = 0; levelID < nlevels; levelID++ )
758
759
                  dlevels[levelID] = (level_sf*levelTable[levelID].level1 +
                                      level_sf*levelTable[levelID].level2)/2.;
760
              else
761
                for (unsigned levelID = 0; levelID < nlevels; levelID++ )
762
                  dlevels[levelID] = level_sf*levelTable[levelID].level1;
763
            }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
764
765
766
767
768
	}

      if ( lbounds )
	{
	  dlevels1 = (double *) malloc(nlevels*sizeof(double));
769
	  for (unsigned levelID = 0; levelID < nlevels; levelID++)
770
	    dlevels1[levelID] = level_sf*levelTable[levelID].level1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
771
	  dlevels2 = (double *) malloc(nlevels*sizeof(double));
772
	  for (unsigned levelID = 0; levelID < nlevels; levelID++)
773
	    dlevels2[levelID] = level_sf*levelTable[levelID].level2;
774
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775

776
      char *unitptr = cdiUnitNamePtr(vartable[varid].level_unit);
777
      zaxisID = varDefZaxis(vlistID, zaxistype, (int)nlevels, dlevels, lbounds, dlevels1, dlevels2,
778
779
780
781
782
783
                            (int)Vctsize, Vct, NULL, NULL, unitptr, 0, 0, ltype1);

      if ( ltype1 != ltype2 && ltype2 != -1 )
        {
          zaxisDefLtype2(zaxisID, ltype2);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
784

785
786
      if ( zaxisInqType(zaxisID) == ZAXIS_REFERENCE )
        {
787
          if ( numberOfVerticalLevels > 0 ) zaxisDefNlevRef(zaxisID, numberOfVerticalLevels);
788
          if ( numberOfVerticalGrid > 0 ) zaxisDefNumber(zaxisID, numberOfVerticalGrid);
Thomas Jahns's avatar
Thomas Jahns committed
789
          if ( !cdiUUIDIsNull(uuidVGrid) ) zaxisDefUUID(zaxisID, uuidVGrid);
790
791
        }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
792
793
794
795
      if ( lbounds ) free(dlevels1);
      if ( lbounds ) free(dlevels2);
      free(dlevels);

796
      /* define new subtype for tile set */
797
798
      int tilesetID = CDI_UNDEFID;
      if ( vartable[varid].tiles ) tilesetID = vlistDefTileSubtype(vlistID, vartable[varid].tiles);
799
800

      /* generate new variable */
801
      int varID = stream_new_var(streamptr, gridID, zaxisID, tilesetID);
802
      varID = vlistDefVarTiles(vlistID, gridID, zaxisID, tsteptype, tilesetID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
803

Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
      vlistDefVarParam(vlistID, varID, param);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
      vlistDefVarDatatype(vlistID, varID, prec);
806
807
      vlistDefVarTimave(vlistID, varID, timave);
      vlistDefVarTimaccu(vlistID, varID, timaccu);
808
      vlistDefVarCompType(vlistID, varID, comptype);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
809

810
811
812
      if ( vartable[varid].typeOfGeneratingProcess != UNDEFID )
        vlistDefVarTypeOfGeneratingProcess(vlistID, varID, vartable[varid].typeOfGeneratingProcess);

813
814
815
      if ( vartable[varid].productDefinitionTemplate != UNDEFID )
        vlistDefVarProductDefinitionTemplate(vlistID, varID, vartable[varid].productDefinitionTemplate);

816
      if ( vartable[varid].lmissval ) vlistDefVarMissval(vlistID, varID, vartable[varid].missval);
817
      if ( vartable[varid].name )     vlistDefVarName(vlistID, varID, vartable[varid].name);
818
      if ( vartable[varid].stdname )  vlistDefVarStdname(vlistID, varID, vartable[varid].stdname);
819
820
      if ( vartable[varid].longname ) vlistDefVarLongname(vlistID, varID, vartable[varid].longname);
      if ( vartable[varid].units )    vlistDefVarUnits(vlistID, varID, vartable[varid].units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821

Uwe Schulzweida's avatar
Uwe Schulzweida committed
822
823
824
825
      if ( vartable[varid].ensdata )  vlistDefVarEnsemble(vlistID, varID, vartable[varid].ensdata->ens_index,
	                                                  vartable[varid].ensdata->ens_count,
							  vartable[varid].ensdata->forecast_init_type);

826
827
828
      int    i;
      vlist_t *vlistptr;
      vlistptr = vlist_to_pointer(vlistID);
829
      for (i=0; i<vartable[varid].opt_grib_nentries; i++)
830
        {
831
          resize_opt_grib_entries(&vlistptr->vars[varID], vlistptr->vars[varID].opt_grib_nentries+1);
832
          vlistptr->vars[varID].opt_grib_nentries += 1;
833
          int idx = vlistptr->vars[varID].opt_grib_nentries-1;
834

835
          vlistptr->vars[varID].opt_grib_kvpair[idx] = vartable[varid].opt_grib_kvpair[i];
836
          vlistptr->vars[varID].opt_grib_kvpair[idx].keyword = NULL;
837
838
839
840
	  if (vartable[varid].opt_grib_kvpair[i].keyword) 
	    vlistptr->vars[varID].opt_grib_kvpair[idx].keyword = 
	      strdupx(vartable[varid].opt_grib_kvpair[i].keyword);
          vlistptr->vars[varID].opt_grib_kvpair[i].update = TRUE;
841
842
843
        }
      /* note: if the key is not defined, we do not throw an error! */

Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
845
      if ( cdiDefaultTableID != UNDEFID )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
846
	  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
847
	  cdiDecodeParam(param, &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
	  if ( tableInqParNamePtr(cdiDefaultTableID, pnum) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
850
851
	    {
	      if ( tableID != UNDEFID )
		{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
852
		  strcpy(name, tableInqParNamePtr(cdiDefaultTableID, pnum));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
		  vlistDefVarName(vlistID, varID, name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
		  if ( tableInqParLongnamePtr(cdiDefaultTableID, pnum) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
855
		    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
856
		      strcpy(longname, tableInqParLongnamePtr(cdiDefaultTableID, pnum));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
858
		      vlistDefVarLongname(vlistID, varID, longname);
		    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
		  if ( tableInqParUnitsPtr(cdiDefaultTableID, pnum) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
860
		    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
		      strcpy(units, tableInqParUnitsPtr(cdiDefaultTableID, pnum));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
		      vlistDefVarUnits(vlistID, varID, units);
		    }
		}
	      else
		tableID = cdiDefaultTableID;
	    }
	  if ( cdiDefaultModelID != UNDEFID ) modelID = cdiDefaultModelID;
	  if ( cdiDefaultInstID  != UNDEFID )  instID = cdiDefaultInstID;
	}

      if ( instID  != UNDEFID ) vlistDefVarInstitut(vlistID, varID, instID);
      if ( modelID != UNDEFID ) vlistDefVarModel(vlistID, varID, modelID);
      if ( tableID != UNDEFID ) vlistDefVarTable(vlistID, varID, tableID);
    }

877
  for ( unsigned index = 0; index < nvars; index++ )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
    {
879
      int varid = varids[index];
880
      unsigned nlevels = vartable[varid].recordTable[0].nlevels;
881

Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
883
884
      /*
      for ( levelID = 0; levelID < nlevels; levelID++ )
	{
Thomas Jahns's avatar
Thomas Jahns committed
885
	  printf("%d %d %d %d %d\n", varid, levelID,
886
887
888
		 vartable[varid].levelTable[levelID].lindex,
		 vartable[varid].levelTable[levelID].recID,
		 vartable[varid].levelTable[levelID].level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
889
890
	}
      */
Thomas Jahns's avatar
Thomas Jahns committed
891
892
893
      unsigned nsub = vartable[varid].nsubtypes >= 0
        ? (unsigned)vartable[varid].nsubtypes : 0U;
      for (size_t isub=0; isub < nsub; isub++)
894
        {
Thomas Jahns's avatar
Thomas Jahns committed
895
896
897
898
          sleveltable_t *restrict streamRecordTable
            = streamptr->vars[index].recordTable + isub;
          leveltable_t *restrict vartableLevelTable
            = vartable[varid].recordTable[isub].levelTable;
899
900
          for (unsigned levelID = 0; levelID < nlevels; levelID++)
            {
Thomas Jahns's avatar
Thomas Jahns committed
901
902
              streamRecordTable->recordID[levelID]
                = vartableLevelTable[levelID].recID;
903
904
              unsigned lindex;
              for (lindex = 0; lindex < nlevels; lindex++ )
Thomas Jahns's avatar
Thomas Jahns committed
905
906
                if ( levelID == (unsigned)vartableLevelTable[lindex].lindex )
                  break;
907
908
              if ( lindex == nlevels )
                Error("Internal problem! lindex not found.");
Thomas Jahns's avatar
Thomas Jahns committed
909
              streamRecordTable->lindex[levelID] = (int)lindex;
910
911
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
913
    }

914
915
  free(varids);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
916
917
918
919
920
921
922
923
924
925
  varFree();
}


void varDefVCT(size_t vctsize, double *vctptr)
{
  if ( Vct == NULL && vctptr != NULL && vctsize > 0 )
    {
      Vctsize = vctsize;
      Vct = (double *) malloc(vctsize*sizeof(double));
926
      memcpy(Vct, vctptr, vctsize*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
927
928
929
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
930

931
void varDefZAxisReference(int nhlev, int nvgrid, unsigned char uuid[CDI_UUID_SIZE])
932
{
933
  numberOfVerticalLevels = nhlev;
934
  numberOfVerticalGrid = nvgrid;
935
  memcpy(uuidVGrid, uuid, CDI_UUID_SIZE);
936
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
937
938


Thomas Jahns's avatar
Thomas Jahns committed
939
int zaxisCompare(int zaxisID, int zaxistype, int nlevels, int lbounds, const double *levels, char *longname, char *units, int ltype1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
940
941
942
943
{
  int differ = 1;
  int levelID;
  int zlbounds = 0;
944
  int ltype_is_equal = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
945

946
  if ( ltype1 == zaxisInqLtype(zaxisID) ) ltype_is_equal = TRUE;
947
948

  if ( ltype_is_equal && (zaxistype == zaxisInqType(zaxisID) || zaxistype == ZAXIS_GENERIC) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
949
950
951
952
953
    {
      if ( zaxisInqLbounds(zaxisID, NULL) > 0 ) zlbounds = 1;
      if ( nlevels == zaxisInqSize(zaxisID) && zlbounds == lbounds )
	{
	  const double *dlevels;
954
955
	  char zlongname[CDI_MAX_NAME];
	  char zunits[CDI_MAX_NAME];
956

Uwe Schulzweida's avatar
Uwe Schulzweida committed
957
958
959
	  dlevels = zaxisInqLevelsPtr(zaxisID);
	  for ( levelID = 0; levelID < nlevels; levelID++ )
	    {
960
	      if ( fabs(dlevels[levelID] - levels[levelID]) > 1.e-9 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
		break;
	    }

	  if ( levelID == nlevels ) differ = 0;

	  if ( ! differ )
	    {
	      zaxisInqLongname(zaxisID, zlongname);
	      zaxisInqUnits(zaxisID, zunits);
	      if ( longname && zlongname[0] )
		{
		  if ( strcmp(longname, zlongname) != 0 ) differ = 1;
		}
	      if ( units && zunits[0] )
		{
		  if ( strcmp(units, zunits) != 0 ) differ = 1;
		}
	    }
	}
    }

  return (differ);
}

985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
struct varDefZAxisSearchState
{
  int resIDValue;
  int zaxistype;
  int nlevels;
  double *levels;
  int lbounds;
  char *longname, *units;
  int ltype;
};

static enum cdiApplyRet
varDefZAxisSearch(int id, void *res, void *data)
{
  struct varDefZAxisSearchState *state = data;
  (void)res;
For faster browsing, not all history is shown. View entire blame