varscan.c 39.4 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
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
  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;
    }

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

  subtype_t *subtype_ptr;
  subtypeAllocate(&subtype_ptr, SUBTYPE_TILES);
448
449
450
  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);
451

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

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

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

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

      if ( name )     if ( name[0] )     vartable[varID].name     = strdup(name);
499
      if ( stdname )  if ( stdname[0] )  vartable[varID].stdname  = strdup(stdname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
501
      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
502
503
504
    }
  else
    {
505
506
507
      char paramstr[32];
      cdiParamToString(param, paramstr, sizeof(paramstr));

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

520
521
  if ( prec > vartable[varID].prec ) vartable[varID].prec = prec;

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

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

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


Uwe Schulzweida's avatar
Uwe Schulzweida committed
544
/*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
static
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546
547
548
549
550
551
552
553
554
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
555
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
556
static
557
int cmpLevelTable(const void* s1, const void* s2)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
559
{
  int cmp = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560
561
  const leveltable_t* x = (const leveltable_t*) s1;
  const leveltable_t* y = (const leveltable_t*) s2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562
563
564
565
566
567
568
569
570
  /*
  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);
}

571
572
573
574
static
int cmpLevelTableInv(const void* s1, const void* s2)
{
  int cmp = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
575
576
  const leveltable_t* x = (const leveltable_t*) s1;
  const leveltable_t* y = (const leveltable_t*) s2;
577
578
579
580
581
582
583
584
585
  /*
  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
586

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


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

602
603
  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
604
605
606
607

  return (cmp);
}

608

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

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

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

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

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

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

652
653
654
655
      gridID     = vartable[varid].gridID;
      param      = vartable[varid].param;
      ltype1     = vartable[varid].ltype1;
      ltype2     = vartable[varid].ltype2;
656
      zaxistype = vartable[varid].zaxistype;
657
      if ( ltype1 == 0 && zaxistype == ZAXIS_GENERIC && cdiDefaultLeveltype != -1 )
658
	zaxistype = cdiDefaultLeveltype;
659
660
661
662
663
664
665
666
667
      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
668

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
672
673
      zaxisID = UNDEFID;

674
675
676
677
678
      /* 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)
          {
679
            fprintf(stderr, "var \"%s\": isub = %d / %d :: "
680
                    "nlevels = %d, vartable[varid].recordTable[isub].nlevels = %d\n",
681
                    vartable[varid].name, isub, vartable[varid].nsubtypes,
682
683
684
685
686
687
                    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;
688
        for (unsigned ilev=0; ilev<nlevels; ilev++)
689
690
691
692
          if ((t1[ilev].level1 != t2[ilev].level1)  ||
              (t1[ilev].level2 != t2[ilev].level2)  ||
              (t1[ilev].lindex != t2[ilev].lindex))
            {
693
              fprintf(stderr, "var \"%s\", varID=%d: isub = %d / %d :: "
694
                      "nlevels = %d, vartable[varid].recordTable[isub].nlevels = %d\n",
695
                      vartable[varid].name, varid, isub, vartable[varid].nsubtypes,
696
                      nlevels, vartable[varid].recordTable[isub].nlevels);
697
698
699
              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);
700
701
702
703
704
              Error("zaxis type must not change for same parameter!");
            }
      }
      leveltable_t *levelTable = vartable[varid].recordTable[0].levelTable;

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

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

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

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

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

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

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

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

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

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

794
      /* define new subtype for tile set */
795
      int tilesetID = vlistDefTileSubtype(vlistID, vartable[varid].tiles);
796
797

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

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

807
808
809
      if ( vartable[varid].typeOfGeneratingProcess != UNDEFID )
        vlistDefVarTypeOfGeneratingProcess(vlistID, varID, vartable[varid].typeOfGeneratingProcess);

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

813
      if ( vartable[varid].lmissval ) vlistDefVarMissval(vlistID, varID, vartable[varid].missval);
814
      if ( vartable[varid].name )     vlistDefVarName(vlistID, varID, vartable[varid].name);
815
      if ( vartable[varid].stdname )  vlistDefVarStdname(vlistID, varID, vartable[varid].stdname);
816
817
      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
818

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

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

832
          vlistptr->vars[varID].opt_grib_kvpair[idx] = vartable[varid].opt_grib_kvpair[i];
833
          vlistptr->vars[varID].opt_grib_kvpair[idx].keyword = NULL;
834
835
836
837
	  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;
838
839
840
        }
      /* note: if the key is not defined, we do not throw an error! */

Uwe Schulzweida's avatar
Uwe Schulzweida committed
841
842
      if ( cdiDefaultTableID != UNDEFID )
	{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
843
	  int pdis, pcat, pnum;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
844
	  cdiDecodeParam(param, &pnum, &pcat, &pdis);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
	  if ( tableInqParNamePtr(cdiDefaultTableID, pnum) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
846
847
848
	    {
	      if ( tableID != UNDEFID )
		{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
		  strcpy(name, tableInqParNamePtr(cdiDefaultTableID, pnum));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
850
		  vlistDefVarName(vlistID, varID, name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851
		  if ( tableInqParLongnamePtr(cdiDefaultTableID, pnum) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
852
		    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
		      strcpy(longname, tableInqParLongnamePtr(cdiDefaultTableID, pnum));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
855
		      vlistDefVarLongname(vlistID, varID, longname);
		    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
856
		  if ( tableInqParUnitsPtr(cdiDefaultTableID, pnum) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
		    {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
858
		      strcpy(units, tableInqParUnitsPtr(cdiDefaultTableID, pnum));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
		      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);
    }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
880
881
882
      /*
      for ( levelID = 0; levelID < nlevels; levelID++ )
	{
883
	  printf("%d %d %d %d %d\n", varID, levelID,
884
885
886
		 vartable[varid].levelTable[levelID].lindex,
		 vartable[varid].levelTable[levelID].recID,
		 vartable[varid].levelTable[levelID].level1);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
888
	}
      */
889
      for (int isub=0; isub<vartable[varid].nsubtypes; isub++)
890
891
892
893
        {
          for (unsigned levelID = 0; levelID < nlevels; levelID++)
            {
              if ( CDI_Debug )
894
                Message("streamptr->vars[%d].recordTable[%d].recordID[%d]=%d",
895
896
897
898
899
900
901
902
903
904
905
                        varID,isub,levelID);
              streamptr->vars[varID].recordTable[isub].recordID[levelID] =
                vartable[varid].recordTable[isub].levelTable[levelID].recID;
              unsigned lindex;
              for (lindex = 0; lindex < nlevels; lindex++ )
                if ( levelID == (unsigned)vartable[varid].recordTable[isub].levelTable[lindex].lindex ) break;
              if ( lindex == nlevels )
                Error("Internal problem! lindex not found.");
              streamptr->vars[varID].recordTable[isub].lindex[levelID] = (int)lindex;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
906
907
    }

908
909
  free(varids);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
910
911
912
913
914
915
916
917
918
919
  varFree();
}


void varDefVCT(size_t vctsize, double *vctptr)
{
  if ( Vct == NULL && vctptr != NULL && vctsize > 0 )
    {
      Vctsize = vctsize;
      Vct = (double *) malloc(vctsize*sizeof(double));
920
      memcpy(Vct, vctptr, vctsize*sizeof(double));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
921
922
923
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
924

925
void varDefZAxisReference(int nhlev, int nvgrid, unsigned char uuid[CDI_UUID_SIZE])
926
{
927
  numberOfVerticalLevels = nhlev;
928
  numberOfVerticalGrid = nvgrid;
929
  memcpy(uuidVGrid, uuid, CDI_UUID_SIZE);
930
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
932


Thomas Jahns's avatar
Thomas Jahns committed
933
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
934
935
936
937
{
  int differ = 1;
  int levelID;
  int zlbounds = 0;
938
  int ltype_is_equal = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
939

940
  if ( ltype1 == zaxisInqLtype(zaxisID) ) ltype_is_equal = TRUE;
941
942

  if ( ltype_is_equal && (zaxistype == zaxisInqType(zaxisID) || zaxistype == ZAXIS_GENERIC) )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
943
944
945
946
947
    {
      if ( zaxisInqLbounds(zaxisID, NULL) > 0 ) zlbounds = 1;
      if ( nlevels == zaxisInqSize(zaxisID) && zlbounds == lbounds )
	{
	  const double *dlevels;
948
949
	  char zlongname[CDI_MAX_NAME];
	  char zunits[CDI_MAX_NAME];
950

Uwe Schulzweida's avatar
Uwe Schulzweida committed
951
952
953
	  dlevels = zaxisInqLevelsPtr(zaxisID);
	  for ( levelID = 0; levelID < nlevels; levelID++ )
	    {
954
	      if ( fabs(dlevels[levelID] - levels[levelID]) > 1.e-9 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
		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);
}

979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
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;
  if (zaxisCompare(id, state->zaxistype, state->nlevels, state->lbounds,
                   state->levels, state->longname, state->units, state->ltype)
      == 0)
    {
      state->resIDValue = id;
      return CDI_APPLY_STOP;
    }
  else
    return CDI_APPLY_GO_ON;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1006

1007
1008
int varDefZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds,
		double *levels1, double *levels2, int vctsize, double *vct, char *name,
1009
		char *longname, char *units, int prec, int mode, int ltype1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1010
1011
1012
1013
1014
{
  /*
    mode: 0 search in vlist and zaxis table
          1 search in zaxis table
   */
1015
  int zaxisdefined = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1016
1017
1018
1019
  int nzaxis;
  int zaxisID = UNDEFID;
  int index;
  int zaxisglobdefined = 0;
1020
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1021
1022
1023
1024
1025
1026
10