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

#include "dmemory.h"
#include "cdi.h"
7
#include "cdi_int.h"
8
#include "error.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
9
#include "vlist.h"
10
#include "zaxis.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
11
#include "varscan.h"
12
#include "namespace.h"
13
#include "resource_handle.h"
Thomas Jahns's avatar
Thomas Jahns committed
14
#include "vlist_var.h"
15
#include "vlist_att.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
16

17
18
19
#include "resource_unpack.h"
#include "serialize.h"

20
21
22
23
24
25
#if  defined  (HAVE_LIBGRIB_API)
/* list of additional GRIB2 keywords which are read by the open process */
int    cdiNAdditionalGRIBKeys = 0;
char*  cdiAdditionalGRIBKeys[MAX_OPT_GRIB_ENTRIES];
#endif

26
27
extern void zaxisGetIndexList ( int, int * );

28
static int VLIST_Debug = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
29
30
31
32
33
34

static void vlist_initialize(void);

#if  defined  (HAVE_LIBPTHREAD)
#  include <pthread.h>

35
static pthread_once_t  _vlist_init_thread = PTHREAD_ONCE_INIT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
36

37
#  define VLIST_INIT()        \
38
  pthread_once(&_vlist_init_thread, vlist_initialize)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
39
40
41

#else

42
static int vlistIsInitialized = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
43

44
#  define VLIST_INIT()               \
45
  if ( !vlistIsInitialized ) vlist_initialize()
46
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
47
48


49
50
static int
vlist_compare(vlist_t *a, vlist_t *b)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
51
{
52
  int diff;
Thomas Jahns's avatar
Thomas Jahns committed
53
54
55
56
57
58
59
60
61
62
  diff = (a->nvars != b->nvars) | (a->ngrids != b->ngrids)
    | (a->nzaxis != b->nzaxis) | (a->instID != b->instID)
    | (a->modelID != b->modelID) | (a->tableID != b->tableID)
    | (a->ntsteps != b->ntsteps) | (a->atts.nelems != b->atts.nelems);
  int nvars = a->nvars;
  for (int varID = 0; varID < nvars; ++varID)
    diff |= vlistVarCompare(a, varID, b, varID);
  int natts = a->atts.nelems;
  for (int attID = 0; attID < natts; ++attID)
    diff |= vlist_att_compare(a, CDI_GLOBAL, b, CDI_GLOBAL, attID);
63
  return diff;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
64
65
}

66
static void
67
vlistPrintKernel(vlist_t *vlistptr, FILE * fp );
68
69
70
static void
vlist_delete(vlist_t *vlistptr);

71
static int  vlistGetSizeP ( void * vlistptr, void *context);
72
static void vlistPackP    ( void * vlistptr, void * buff, int size,
73
                            int *position, void *context);
74
static int  vlistTxCode   ( void );
75

76
77
78
79
#if !defined(__cplusplus)
const
#endif
resOps vlist_ops = {
80
  (valCompareFunc)vlist_compare,
81
  (valDestroyFunc)vlist_delete,
82
83
  (valPrintFunc)vlistPrintKernel
  , vlistGetSizeP,
84
85
  vlistPackP,
  vlistTxCode
86
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87
88


89
vlist_t *vlist_to_pointer(int code)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
90
{
91
  VLIST_INIT();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
92
  return (vlist_t*) reshGetVal(code, &vlist_ops );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
94
}

95
96
static
void vlist_init_entry(vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
97
{
98
  vlistptr->self           = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
100
101
102
  vlistptr->nvars          = 0;
  vlistptr->vars           = NULL;
  vlistptr->ngrids         = 0;
  vlistptr->nzaxis         = 0;
103
  vlistptr->taxisID        = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104
105
106
107
108
  vlistptr->instID         = cdiDefaultInstID;
  vlistptr->modelID        = cdiDefaultModelID;
  vlistptr->tableID        = cdiDefaultTableID;
  vlistptr->varsAllocated  = 0;
  vlistptr->ntsteps        = CDI_UNDEFID;
109
  vlistptr->atts.nalloc    = MAX_ATTRIBUTES;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
110
  vlistptr->atts.nelems    = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
111
112
}

113
static
114
vlist_t *vlist_new_entry(cdiResH resH)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
115
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
116
  vlist_t *vlistptr = (vlist_t*) xmalloc(sizeof(vlist_t));
117
  vlist_init_entry(vlistptr);
118
119
120
121
122
123
124
  if (resH == CDI_UNDEFID)
    vlistptr->self = reshPut(vlistptr, &vlist_ops);
  else
    {
      vlistptr->self = resH;
      reshReplace(resH, vlistptr, &vlist_ops);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
125
126
127
  return (vlistptr);
}

128
129
static
void vlist_delete_entry(vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
130
{
Thomas Jahns's avatar
Thomas Jahns committed
131
  int idx;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
132
133
134

  idx = vlistptr->self;

135
  reshRemove(idx, &vlist_ops );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
136
137
138
139

  free(vlistptr);

  if ( VLIST_Debug )
140
    Message("Removed idx %d from vlist list", idx);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141
142
}

143
144
static
void vlist_initialize(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
145
146
147
148
149
{
  char *env;

  env = getenv("VLIST_DEBUG");
  if ( env ) VLIST_Debug = atoi(env);
150
151
152
#ifndef HAVE_LIBPTHREAD
  vlistIsInitialized = TRUE;
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
153
154
}

155
156
static
void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
{
158
  int vlistID2 = vlistptr2->self;
159
  memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
  vlistptr2->atts.nelems = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
161
162
163
  vlistptr2->self = vlistID2;
}

164
165
static
void vlist_check_ptr(const char *caller, vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
166
167
{
  if ( vlistptr == NULL )
168
    Errorc("vlist undefined!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
169
170
171
}

/*
172
@Function  vlistCreate
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
174
@Title     Create a variable list

175
@Prototype int vlistCreate(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
176

Uwe Schulzweida's avatar
Uwe Schulzweida committed
177
178
179
180
181
182
183
184
185
186
@Example
Here is an example using @func{vlistCreate} to create a variable list
and add a variable with @func{vlistDefVar}.

@Source
#include "cdi.h"
   ...
int vlistID, varID;
   ...
vlistID = vlistCreate();
187
varID = vlistDefVar(vlistID, gridID, zaxisID, TSTEP_INSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
188
189
190
191
192
193
   ...
streamDefVlist(streamID, vlistID);
   ...
vlistDestroy(vlistID);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
194
195
@EndFunction
*/
196
int vlistCreate(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
197
{
198
199
  cdiInitialize();

200
  VLIST_INIT();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
201

202
203
  vlist_t *vlistptr = vlist_new_entry(CDI_UNDEFID);
  return (vlistptr->self);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204
205
}

206
207
static void
vlist_delete(vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208
{
209
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210

211
212
  int vlistID = vlistptr->self;

Deike Kleberg's avatar
Deike Kleberg committed
213
  vlistDelAtts(vlistID, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214

215
  int nvars = vlistptr->nvars;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216

217
  for (int varID = 0; varID < nvars; varID++ )
Deike Kleberg's avatar
Deike Kleberg committed
218
219
220
221
222
223
    {
      if ( vlistptr->vars[varID].levinfo )  free(vlistptr->vars[varID].levinfo);
      if ( vlistptr->vars[varID].name )     free(vlistptr->vars[varID].name);
      if ( vlistptr->vars[varID].longname ) free(vlistptr->vars[varID].longname);
      if ( vlistptr->vars[varID].stdname )  free(vlistptr->vars[varID].stdname);
      if ( vlistptr->vars[varID].units )    free(vlistptr->vars[varID].units);
224
225

      if ( vlistptr->vars[varID].ensdata )  free(vlistptr->vars[varID].ensdata);
226

227
#if  defined  (HAVE_LIBGRIB_API)
228
      for (int i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++) {
229
230
231
	if ( vlistptr->vars[varID].opt_grib_int_keyword[i] )
	  free(vlistptr->vars[varID].opt_grib_int_keyword[i]);
      }
232
      for (int i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++) {
233
234
235
	if ( vlistptr->vars[varID].opt_grib_dbl_keyword[i] )
	  free(vlistptr->vars[varID].opt_grib_dbl_keyword[i]);
      }
236
#endif
237

Deike Kleberg's avatar
Deike Kleberg committed
238
      vlistDelAtts(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
239
    }
240

Deike Kleberg's avatar
Deike Kleberg committed
241
  if ( vlistptr->vars ) free(vlistptr->vars);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242

Deike Kleberg's avatar
Deike Kleberg committed
243
  vlist_delete_entry(vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
245
}

246
247
248
249
250
251
252

/*
@Function  vlistDestroy
@Title     Destroy a variable list

@Prototype void vlistDestroy(int vlistID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
253
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
254
255
256
257
258

@EndFunction
*/
void vlistDestroy(int vlistID)
{
259
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
260
261
262
263

  vlist_delete(vlistptr);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
264
265
266
267
268
269
/*
@Function  vlistCopy
@Title     Copy a variable list

@Prototype void vlistCopy(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
270
271
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
273

@Description
274
The function @func{vlistCopy} copies all entries from vlistID1 to vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
275
276
277
278
279

@EndFunction
*/
void vlistCopy(int vlistID2, int vlistID1)
{
280
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
281
282
283
284

  vlistptr1 = vlist_to_pointer(vlistID1);
  vlistptr2 = vlist_to_pointer(vlistID2);

285
286
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
287

Thomas Jahns's avatar
Thomas Jahns committed
288
  var_t *vlist2vars = vlistptr2->vars;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
289
290
  vlist_copy(vlistptr2, vlistptr1);

291
  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
292

Uwe Schulzweida's avatar
Uwe Schulzweida committed
293
294
295
296
  if ( vlistptr1->vars )
    {
      int nvars = vlistptr1->nvars;

297
      //vlistptr2->varsAllocated = nvars;
Thomas Jahns's avatar
Thomas Jahns committed
298
      vlistptr2->vars = xrealloc(vlist2vars, vlistptr2->varsAllocated*sizeof(var_t));
299
      memcpy(vlistptr2->vars, vlistptr1->vars, vlistptr2->varsAllocated*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
300

301
      for ( int varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
302
303
304
        {
          if ( vlistptr1->vars[varID].name )
            vlistptr2->vars[varID].name = strdupx(vlistptr1->vars[varID].name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
305

Thomas Jahns's avatar
Thomas Jahns committed
306
307
          if ( vlistptr1->vars[varID].longname )
            vlistptr2->vars[varID].longname = strdupx(vlistptr1->vars[varID].longname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308

Thomas Jahns's avatar
Thomas Jahns committed
309
310
          if ( vlistptr1->vars[varID].stdname )
            vlistptr2->vars[varID].stdname = strdupx(vlistptr1->vars[varID].stdname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
311

Thomas Jahns's avatar
Thomas Jahns committed
312
313
          if ( vlistptr1->vars[varID].units )
            vlistptr2->vars[varID].units = strdupx(vlistptr1->vars[varID].units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
314

315
316
317
318
319
320
          if ( vlistptr1->vars[varID].ensdata )
            {
              vlistptr2->vars[varID].ensdata = (ensinfo_t *) malloc(sizeof(ensinfo_t));
              memcpy(vlistptr2->vars[varID].ensdata,
                     vlistptr1->vars[varID].ensdata, sizeof(ensinfo_t));
            }
321
#if  defined  (HAVE_LIBGRIB_API)
322
323
324
325
326
          /* ---------------------------------- */
          /* Local change: 2013-01-28, FP (DWD) */
          /* ---------------------------------- */

	  vlistptr2->vars[varID].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
327
	  for (int i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
328
329
330
	    if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
	      vlistptr2->vars[varID].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
	      vlistptr2->vars[varID].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
331
	      vlistptr2->vars[varID].opt_grib_int_update[i]  = TRUE;
332
333
334
	    }
	  }
	  vlistptr2->vars[varID].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
335
	  for (int i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
336
337
338
	    if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
	      vlistptr2->vars[varID].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
	      vlistptr2->vars[varID].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
339
	      vlistptr2->vars[varID].opt_grib_dbl_update[i]  = TRUE;
340
341
	    }
	  }
342
#endif
343

344
345
	  vlistptr2->vars[varID].atts.nelems = 0;
	  vlistCopyVarAtts(vlistID1, varID, vlistID2, varID);
346

347
348
          if ( vlistptr1->vars[varID].levinfo )
            {
349
              int nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
350
351
352
353
              vlistptr2->vars[varID].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
              memcpy(vlistptr2->vars[varID].levinfo,
                     vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
            }
354
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
356
357
358
359
360
361
362
363
    }
}

/*
@Function  vlistDuplicate
@Title     Duplicate a variable list

@Prototype int vlistDuplicate(int vlistID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
365
366

@Description
367
The function @func{vlistDuplicate} duplicates the variable list from vlistID1.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
368
369

@Result
370
@func{vlistDuplicate} returns an identifier to the duplicated variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371
372
373
374
375
376

@EndFunction
*/
int vlistDuplicate(int vlistID)
{
  int vlistIDnew;
377
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
378

379
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
380

381
  vlistIDnew = vlistCreate();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
382
383
384
385
386
387
388
389
390
391

  vlistCopy(vlistIDnew, vlistID);

  return (vlistIDnew);
}


void vlistClearFlag(int vlistID)
{
  int varID, levID;
392
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
393
394
395
396

  for ( varID = 0; varID < vlistptr->nvars; varID++ )
    {
      vlistptr->vars[varID].flag = FALSE;
397
      if ( vlistptr->vars[varID].levinfo )
398
399
400
401
402
403
404
        {
          int nlevs = zaxisInqSize(vlistptr->vars[varID].zaxisID);
          for ( levID = 0; levID < nlevs; levID++ )
            {
              vlistptr->vars[varID].levinfo[levID].flag = FALSE;
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
405
406
407
    }
}

408
409
410
static
int vlist_generate_zaxis(int vlistID, int zaxistype, int nlevels, double *levels,
                         double *lbounds, double *ubounds, int vctsize, const double *vct)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
411
412
413
{
  int zaxisID = CDI_UNDEFID;
  int zaxisglobdefined = 0;
414
  int has_bounds = FALSE;
415
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
416

417
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
418

419
420
  int zaxisdefined = 0;
  int nzaxis = vlistptr->nzaxis;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
421

422
423
  if ( lbounds && ubounds ) has_bounds = TRUE;

424
  for ( int index = 0; index < nzaxis; ++index )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
425
426
427
    {
      zaxisID = vlistptr->zaxisIDs[index];

428
      if ( zaxisCompare(zaxisID, zaxistype, nlevels, has_bounds, levels, NULL, NULL, 0) == 0 )
Thomas Jahns's avatar
Thomas Jahns committed
429
430
431
432
        {
          zaxisdefined = 1;
          break;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
433
434
435
436
437
    }

  if ( ! zaxisdefined )
    {
      nzaxis = zaxisSize();
438
439
      if ( nzaxis > 0 )
        {
440
          int *zaxisIndexList = (int *)xmalloc(nzaxis * sizeof (int));
Thomas Jahns's avatar
Thomas Jahns committed
441
          reshLock();
442
          zaxisGetIndexList ( nzaxis, zaxisIndexList );
443
          for ( int index = 0; index < nzaxis; ++index )
444
445
446
447
448
449
450
451
            {
              zaxisID = zaxisIndexList[index];
              if ( zaxisCompare(zaxisID, zaxistype, nlevels, has_bounds, levels, NULL, NULL, 0) == 0 )
                {
                  zaxisglobdefined = 1;
                  break;
                }
            }
Thomas Jahns's avatar
Thomas Jahns committed
452
          reshUnlock();
453
          free(zaxisIndexList);
454
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
455
456
457
458
459
    }

  if ( ! zaxisdefined )
    {
      if ( ! zaxisglobdefined )
460
461
462
	{
	  zaxisID = zaxisCreate(zaxistype, nlevels);
	  zaxisDefLevels(zaxisID, levels);
463
	  if ( has_bounds )
464
	    {
465
466
	      zaxisDefLbounds(zaxisID, lbounds);
	      zaxisDefUbounds(zaxisID, ubounds);
467
468
469
470
471
472
473
474
475
476
	    }

	  if ( zaxistype == ZAXIS_HYBRID )
	    {
	      if ( vctsize > 0 )
		zaxisDefVct(zaxisID, vctsize, vct);
	      else
		Warning("VCT missing");
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491

      nzaxis = vlistptr->nzaxis;
      vlistptr->zaxisIDs[nzaxis] = zaxisID;
      vlistptr->nzaxis++;
    }

  return (zaxisID);
}

/*
@Function  vlistCopyFlag
@Title     Copy some entries of a variable list

@Prototype void vlistCopyFlag(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494
495

@Description
496
The function @func{vlistCopyFlag} copies all entries with a flag from vlistID1 to vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
497
498
499
500
501

@EndFunction
*/
void vlistCopyFlag(int vlistID2, int vlistID1)
{
502
503
  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
    *vlistptr2 = vlist_to_pointer(vlistID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504

505
506
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507
508

  vlist_copy(vlistptr2, vlistptr1);
Thomas Jahns's avatar
Thomas Jahns committed
509

510
  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511

Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
514
  if ( vlistptr1->vars )
    {
      int nvars = vlistptr1->nvars;
515
516
      int nvars2 = 0;
      int varID2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
518
519
520
521
      int index;

      vlistptr2->ngrids = 0;
      vlistptr2->nzaxis = 0;

522
523
      for ( int varID = 0; varID < nvars; varID++ )
        nvars2 += (vlistptr1->vars[varID].flag != 0);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525

      vlistptr2->nvars = nvars2;
526
      vlistptr2->varsAllocated = nvars2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
527
      if ( nvars2 > 0 )
528
        vlistptr2->vars  = (var_t *)xmalloc(nvars2*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
      else
Thomas Jahns's avatar
Thomas Jahns committed
530
        vlistptr2->vars  = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
532

      varID2 = 0;
533
      for ( int varID = 0; varID < nvars; varID++ )
534
535
536
	if ( vlistptr1->vars[varID].flag )
	  {
	    vlistptr2->vars[varID2].flag = FALSE;
537
538
	    int zaxisID = vlistptr1->vars[varID].zaxisID;
	    int gridID  = vlistptr1->vars[varID].gridID;
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558

	    memcpy(&vlistptr2->vars[varID2], &vlistptr1->vars[varID], sizeof(var_t));

	    vlistptr1->vars[varID].fvarID = varID2;
	    vlistptr2->vars[varID2].fvarID = varID;

	    vlistptr2->vars[varID2].mvarID = varID2;

	    if ( vlistptr1->vars[varID].name )
	      vlistptr2->vars[varID2].name = strdupx(vlistptr1->vars[varID].name);

	    if ( vlistptr1->vars[varID].longname )
	      vlistptr2->vars[varID2].longname = strdupx(vlistptr1->vars[varID].longname);

	    if ( vlistptr1->vars[varID].stdname )
	      vlistptr2->vars[varID2].stdname = strdupx(vlistptr1->vars[varID].stdname);

	    if ( vlistptr1->vars[varID].units )
	      vlistptr2->vars[varID2].units = strdupx(vlistptr1->vars[varID].units);

559
560
            if ( vlistptr1->vars[varID].ensdata )
              {
561
                vlistptr2->vars[varID2].ensdata = (ensinfo_t *)xmalloc(sizeof(ensinfo_t));
562
563
564
565
                memcpy(vlistptr2->vars[varID2].ensdata,
                       vlistptr1->vars[varID].ensdata, sizeof(ensinfo_t));
              }

566
#if  defined  (HAVE_LIBGRIB_API)
567
568
569
570
571
572
573
574
575
576
	    /* ---------------------------------- */
	    /* Local change: 2013-01-28, FP (DWD) */
	    /* ---------------------------------- */

	    int i;
	    vlistptr2->vars[varID2].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
	    for (i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
	      if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
		vlistptr2->vars[varID2].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
		vlistptr2->vars[varID2].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
577
                vlistptr2->vars[varID2].opt_grib_int_update[i]  = TRUE;
578
579
580
581
582
583
584
	      }
	    }
	    vlistptr2->vars[varID2].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
	    for (i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
	      if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
		vlistptr2->vars[varID2].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
		vlistptr2->vars[varID2].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
585
                vlistptr2->vars[varID2].opt_grib_dbl_update[i]  = TRUE;
586
587
	      }
	    }
588
#endif
589
590
591
592

	    vlistptr2->vars[varID2].atts.nelems = 0;
	    vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);

593
594
	    int nlevs  = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
	    int nlevs2 = 0;
595
            if ( vlistptr1->vars[varID].levinfo )
596
597
              for ( int levID = 0; levID < nlevs; levID++ )
                nlevs2 += (vlistptr1->vars[varID].levinfo[levID].flag != 0);
598

599
	    vlistptr2->vars[varID2].levinfo = (levinfo_t *)xmalloc(nlevs2*sizeof(levinfo_t));
600
601
602
603

	    if ( nlevs != nlevs2 )
	      {
		int nvct = 0;
604
		double *lbounds = NULL, *ubounds = NULL;
605
		const double *vct = NULL;
606
                char ctemp[CDI_MAX_NAME];
607
608

		zaxisID = vlistptr1->vars[varID].zaxisID;
609
610
		double *levels = (double *)xmalloc(nlevs2*sizeof(double));
                int levID2 = 0;
611
612
                if (!vlistptr1->vars[varID].levinfo)
                  cdiVlistCreateVarLevInfo(vlistptr1, varID);
613
614
615
616
617
618
619
620
                for ( int levID = 0; levID < nlevs; ++levID )
                  if ( vlistptr1->vars[varID].levinfo[levID].flag )
                    {
                      vlistptr1->vars[varID].levinfo[levID].flevelID = levID2;
                      vlistptr1->vars[varID].levinfo[levID].mlevelID = levID2;
                      levels[levID2++] = zaxisInqLevel(zaxisID, levID);
                    }
		int zaxisType = zaxisInqType(zaxisID);
621
622
623
624
625
626

		if ( zaxisType == ZAXIS_HYBRID )
		  {
		    nvct = zaxisInqVctSize(zaxisID);
		    vct  = zaxisInqVctPtr(zaxisID);
		  }
627
628
629

                if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
                  {
630
631
632
633
634
                    lbounds = (double *)xmalloc(2 * nlevs2*sizeof(double));
                    ubounds = lbounds + nlevs2;

                    double *lbounds1 = (double *)xmalloc(2 * nlevs*sizeof(double)),
                      *ubounds1 = lbounds1 + nlevs;
635
636
637
638

                    zaxisInqLbounds(zaxisID, lbounds1);
                    zaxisInqUbounds(zaxisID, ubounds1);

639
640
                    int levID2 = 0;
                    for ( int levID = 0; levID < nlevs; ++levID )
641
642
643
644
645
646
647
648
649
650
                      if ( vlistptr1->vars[varID].levinfo[levID].flag )
                        {
                          lbounds[levID2] = lbounds1[levID];
                          ubounds[levID2] = ubounds1[levID];
                          levID2++;
                        }

                    free(lbounds1);
                  }

651
		int zaxisID2 = vlist_generate_zaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, ubounds, nvct, vct);
652
		free(levels);
653
                free(lbounds);
654

655
656
657
658
659
660
                zaxisInqName(zaxisID, ctemp);
                zaxisDefName(zaxisID2, ctemp);
                zaxisInqLongname(zaxisID, ctemp);
                zaxisDefLongname(zaxisID2, ctemp);
                zaxisInqUnits(zaxisID, ctemp);
                zaxisDefUnits(zaxisID2, ctemp);
661
662
663
664
665

		zaxisID = zaxisID2;
		vlistptr2->vars[varID2].zaxisID = zaxisID2;
	      }

666
	    for ( int levID = 0; levID < nlevs2; levID++ )
667
668
669
670
671
	      {
		vlistptr2->vars[varID2].levinfo[levID].flag  = FALSE;
		vlistptr2->vars[varID2].levinfo[levID].index = -1;
	      }

672
673
	    int levID2 = 0;
	    for ( int levID = 0; levID < nlevs; levID++ )
674
675
676
677
678
679
680
	      if ( vlistptr1->vars[varID].levinfo[levID].flag )
		{
		  vlistptr2->vars[varID2].levinfo[levID2].flevelID = levID;
		  vlistptr2->vars[varID2].levinfo[levID2].mlevelID = levID;
		  levID2++;
		}

681
            vlistAdd2GridIDs(vlistptr2, gridID);
682
683
684
685
686
687
688
689
690
691
692
693
694

	    for ( index = 0; index < vlistptr2->nzaxis; index++ )
	      if ( vlistptr2->zaxisIDs[index] == zaxisID ) break;

	    if ( index == vlistptr2->nzaxis )
	      {
		vlistptr2->zaxisIDs[vlistptr2->nzaxis++] = zaxisID;
		if (vlistptr2->nzaxis >= MAX_ZAXES_PS )
		  Error("Internal Problem! More than %d zaxis.", MAX_ZAXES_PS);
	      }

	    varID2++;
	  }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
695
696
697
698
699
700
701
702
703
    }
}

/*
@Function  vlistCat
@Title     Concatenate two variable lists

@Prototype void vlistCat(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
704
705
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
706
707
708
709
710
711
712
713
714
715
716

@Description
Concatenate the variable list vlistID1 at the end of vlistID2.

@EndFunction
*/
void vlistCat(int vlistID2, int vlistID1)
{
  int nvars, nvars1, nvars2;
  int varID, varID2, nlevs;
  int index, gridID, zaxisID;
717
718
  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
    *vlistptr2 = vlist_to_pointer(vlistID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719

720
721
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722
723
724
725
726
727

  nvars1 = vlistptr1->nvars;
  nvars2 = vlistptr2->nvars;
  nvars = nvars1 + nvars2;
  vlistptr2->nvars = nvars;

728
729
730
731
732
  if ( nvars > vlistptr2->varsAllocated )
    {
      vlistptr2->varsAllocated = nvars;
      vlistptr2->vars = (var_t *) realloc(vlistptr2->vars, nvars*sizeof(var_t));
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
733
  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars, nvars1*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
735
736
737
738
739
740

  for ( varID = 0; varID < nvars1; varID++ )
    {
      varID2 = varID + nvars2;
      vlistptr1->vars[varID].fvarID = varID2;
      vlistptr2->vars[varID2].fvarID = varID;

741
742
743
      vlistptr1->vars[varID].mvarID = varID2;
      vlistptr2->vars[varID2].mvarID = varID;

744
      if ( vlistptr1->vars[varID].param < 0 )
745
746
747
	{
	  int pnum, pcat, pdis;
	  cdiDecodeParam(vlistptr1->vars[varID].param, &pnum, &pcat, &pdis);
748
	  pnum = -(varID2+1);
749
750
	  vlistptr2->vars[varID2].param = cdiEncodeParam(pnum, pcat, pdis);
	}
751

Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
      if ( vlistptr1->vars[varID].name )
Thomas Jahns's avatar
Thomas Jahns committed
753
        vlistptr2->vars[varID2].name = strdupx(vlistptr1->vars[varID].name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
755

      if ( vlistptr1->vars[varID].longname )
Thomas Jahns's avatar
Thomas Jahns committed
756
        vlistptr2->vars[varID2].longname = strdupx(vlistptr1->vars[varID].longname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
758

      if ( vlistptr1->vars[varID].stdname )
Thomas Jahns's avatar
Thomas Jahns committed
759
        vlistptr2->vars[varID2].stdname = strdupx(vlistptr1->vars[varID].stdname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
760
761

      if ( vlistptr1->vars[varID].units )
Thomas Jahns's avatar
Thomas Jahns committed
762
        vlistptr2->vars[varID2].units = strdupx(vlistptr1->vars[varID].units);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
763

764
      nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
765
766
767
768
769
      if (vlistptr1->vars[varID].levinfo)
        {
          vlistptr2->vars[varID2].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
          memcpy(vlistptr2->vars[varID2].levinfo, vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
770

771
772
773
774
775
776
      if ( vlistptr1->vars[varID].ensdata )
        {
          vlistptr2->vars[varID2].ensdata = (ensinfo_t *) malloc(sizeof(ensinfo_t));
          memcpy(vlistptr2->vars[varID2].ensdata, vlistptr1->vars[varID].ensdata, sizeof(ensinfo_t));
        }

777
#if  defined  (HAVE_LIBGRIB_API)
778
779
780
781
782
783
784
785
786
787
      /* ---------------------------------- */
      /* Local change: 2013-01-28, FP (DWD) */
      /* ---------------------------------- */

      int i;
      vlistptr2->vars[varID2].opt_grib_int_nentries = vlistptr1->vars[varID].opt_grib_int_nentries;
      for (i=0; i<vlistptr1->vars[varID].opt_grib_int_nentries; i++) {
	if ( vlistptr1->vars[varID].opt_grib_int_keyword[i] ) {
	  vlistptr2->vars[varID2].opt_grib_int_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_int_keyword[i]);
	  vlistptr2->vars[varID2].opt_grib_int_val[i]     = vlistptr1->vars[varID].opt_grib_int_val[i];
788
          vlistptr2->vars[varID2].opt_grib_int_update[i]  = TRUE;
789
790
791
792
793
794
795
	}
      }
      vlistptr2->vars[varID2].opt_grib_dbl_nentries = vlistptr1->vars[varID].opt_grib_dbl_nentries;
      for (i=0; i<vlistptr1->vars[varID].opt_grib_dbl_nentries; i++) {
	if ( vlistptr1->vars[varID].opt_grib_dbl_keyword[i] ) {
	  vlistptr2->vars[varID2].opt_grib_dbl_keyword[i] = strdupx(vlistptr1->vars[varID].opt_grib_dbl_keyword[i]);
	  vlistptr2->vars[varID2].opt_grib_dbl_val[i]     = vlistptr1->vars[varID].opt_grib_dbl_val[i];
796
          vlistptr2->vars[varID2].opt_grib_dbl_update[i]  = TRUE;
797
798
	}
      }
799
#endif
800

801
802
803
      vlistptr2->vars[varID2].atts.nelems = 0;
      vlistCopyVarAtts(vlistID1, varID, vlistID2, varID2);

Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
      gridID = vlistptr1->vars[varID].gridID;
805
      vlistAdd2GridIDs(vlistptr2, gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
806
807
808

      zaxisID = vlistptr1->vars[varID].zaxisID;
      for ( index = 0; index < vlistptr2->nzaxis; index++ )
Thomas Jahns's avatar
Thomas Jahns committed
809
        if ( zaxisID == vlistptr2->zaxisIDs[index] ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
810
811

      if ( index == vlistptr2->nzaxis )
812
813
814
815
816
	{
	  vlistptr2->zaxisIDs[vlistptr2->nzaxis++] = zaxisID;
	  if ( vlistptr2->nzaxis >= MAX_ZAXES_PS )
	    Error("Internal Problem! More than %d zaxis.", MAX_ZAXES_PS);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
817
818
819
820
821
822
823
824
825
    }
}

/*
@Function  vlistMerge
@Title     Merge two variable lists

@Prototype void vlistMerge(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
826
827
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828
829

@Description
Uwe Schulzweida's avatar
Uwe Schulzweida committed
830
Merge the variable list vlistID1 to the variable list vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831
832
833
834
835

@EndFunction
*/
void vlistMerge(int vlistID2, int vlistID1)
{
836
837
838
  int varID = 0;
  vlist_t *vlistptr1 = vlist_to_pointer(vlistID1),
    *vlistptr2 = vlist_to_pointer(vlistID2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
839

840
841
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
842

843
844
  int nvars1 = vlistptr1->nvars;
  int nvars2 = vlistptr2->nvars;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
847
848

  if ( nvars1 == nvars2 )
    {
      for ( varID = 0; varID < nvars2; varID++ )
849
850
851
852
853
854
855
856
857
858
859
860
	{
	  if ( vlistptr1->vars[varID].name && vlistptr2->vars[varID].name )
	    {
	      if ( strcmp(vlistptr1->vars[varID].name,
			  vlistptr2->vars[varID].name) != 0 ) break;
	    }
	  else
	    {
	      if ( vlistptr1->vars[varID].param != vlistptr2->vars[varID].param )
		break;
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
861
862
863
864
865
    }

  if ( varID == nvars2 ) /* same variables in vlistID1 and vlistID2 */
    {
      for ( varID = 0; varID < nvars2; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
866
867
868
        {
          vlistptr1->vars[varID].fvarID = varID;
          vlistptr2->vars[varID].fvarID = varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869

Thomas Jahns's avatar
Thomas Jahns committed
870
871
          vlistptr1->vars[varID].mvarID = varID;
          vlistptr2->vars[varID].mvarID = varID;
872

873
874
          int nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
          int nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
875

876
          int nlevs = nlevs1 + nlevs2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
877

Thomas Jahns's avatar
Thomas Jahns committed
878
879
880
          /*
          fprintf(stderr, "var %d %d %d %d %d\n", varID, nlevs1, nlevs2, nlevs, sizeof(levinfo_t));
          */
881
882
          if (vlistptr1->vars[varID].levinfo)
            {
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
              vlistptr2->vars[varID].levinfo = (levinfo_t*)
884
                xrealloc(vlistptr2->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
885

886
887
888
889
890
              memcpy(vlistptr2->vars[varID].levinfo+nlevs2,
                     vlistptr1->vars[varID].levinfo, nlevs1*sizeof(levinfo_t));
            }
          else
            cdiVlistCreateVarLevInfo(vlistptr1, varID);
891
	  for ( int levID = 0; levID < nlevs1; levID++ )
892
893
894
895
	    {
	      vlistptr1->vars[varID].levinfo[levID].mlevelID = nlevs2 + levID;
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896

897
      int *lvar = (int *)xcalloc(nvars2, sizeof(int));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898
899

      for ( varID = 0; varID < nvars2; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
900
901
902
        {
          if ( lvar[varID] == TRUE ) continue;

903
904
          int zaxisID1 = vlistptr1->vars[varID].zaxisID;
          int zaxisID2 = vlistptr2->vars[varID].zaxisID;
Thomas Jahns's avatar
Thomas Jahns committed
905
          /*
906
907
          nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
          nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
Thomas Jahns's avatar
Thomas Jahns committed
908
          */
909
910
          int nlevs1 = zaxisInqSize(zaxisID1);
          int nlevs2 = zaxisInqSize(zaxisID2);
Thomas Jahns's avatar
Thomas Jahns committed
911
912
913
          /*
          fprintf(stderr, "zaxis %d %d %d %d\n", zaxisID1, zaxisID2, nlevs1, nlevs2);
          */
914
          int nlevs = nlevs1 + nlevs2;
Thomas Jahns's avatar
Thomas Jahns committed
915

916
          int zaxisID = zaxisDuplicate(zaxisID2);
Thomas Jahns's avatar
Thomas Jahns committed
917
918
919

          zaxisResize(zaxisID, nlevs);

920
          double *levels = (double *)xmalloc(nlevs1*sizeof(double));
Thomas Jahns's avatar
Thomas Jahns committed
921
922
923
924
925
926

          zaxisInqLevels(zaxisID1, levels);
          /*
          for ( levID = 0; levID < nlevs1; levID++ )
            fprintf(stderr, "%d %d %d %d %d %g\n", varID, levID, nlevs1, nlevs2, vlistptr2->vars[varID].nlevs, levels[levID]);
          */
927
          for ( int levID = 0; levID < nlevs1; levID++ )
Thomas Jahns's avatar
Thomas Jahns committed
928
929
930
931
            zaxisDefLevel(zaxisID, nlevs2+levID, levels[levID]);

          free(levels);

932
          for ( int index = 0; index < vlistptr2->nzaxis; index++ )
Thomas Jahns's avatar
Thomas Jahns committed
933
934
935
            if ( vlistptr2->zaxisIDs[index] == zaxisID2 )
              vlistptr2->zaxisIDs[index] = zaxisID;

936
          for ( int varID2 = 0; varID2 < nvars2; varID2++ )
Thomas Jahns's avatar
Thomas Jahns committed
937
938
939
940
941
942
            if ( lvar[varID2] == FALSE && vlistptr2->vars[varID2].zaxisID == zaxisID2 )
              {
                vlistptr2->vars[varID2].zaxisID = zaxisID;
                lvar[varID2] = TRUE;
              }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957

      free(lvar);
    }
  else
    {
      vlistCat(vlistID2, vlistID1);
    }
}

/*
@Function  vlistNvars
@Title     Number of variables in a variable list

@Prototype int vlistNvars(int vlistID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
958
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
959
960

@Description
961
The function @func{vlistNvars} returns the number of variables in the variable list vlistID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
962
963

@Result
964
@func{vlistNvars} returns the number of variables in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
965
966
967
968
969

@EndFunction
*/
int vlistNvars(int vlistID)
{
970
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
971

972
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
973
974
975
976

  return (vlistptr->nvars);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
977

Uwe Schulzweida's avatar
Uwe Schulzweida committed
978
979
int vlistNrecs(int vlistID)
{
980
981
  int nrecs = 0;
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
982

983
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
984

985
  for ( int varID = 0; varID < vlistptr->nvars; varID++ )
986
    nrecs +=  zaxisInqSize(vlistptr->vars[varID].zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
987
988
989
990
991

  return (nrecs);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
992
993
int vlistNumber(int vlistID)
{
994
995
  int number, number2, datatype;
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
996

997
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
998

999
1000
1001
1002
1003
1004
  datatype = vlistptr->vars[0].datatype;
  if (  datatype== DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
    number = CDI_COMP;
  else
    number = CDI_REAL;

1005
  for ( int varID = 1; varID < vlistptr->nvars; varID++ )
1006
1007
1008
    {
      datatype = vlistptr->vars[varID].datatype;
      if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
Thomas Jahns's avatar
Thomas Jahns committed
1009
        number2 = CDI_COMP;
1010
      else
Thomas Jahns's avatar
Thomas Jahns committed
1011
        number2 = CDI_REAL;
1012
1013

      if ( number2 != number )
Thomas Jahns's avatar
Thomas Jahns committed
1014
1015
1016
1017
        {
          number = CDI_BOTH;
          break;
        }
1018
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1019
1020
1021
1022

  return (number);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1023
1024
1025
1026
1027
1028
/*
@Function  vlistNgrids
@Title     Number of grids in a variable list

@Prototype int vlistNgrids(int vlistID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1029
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1030
1031

@Description
1032
The function @func{vlistNgrids} returns the number of grids in the variable list vlistID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1033
1034

@Result
1035
@func{vlistNgrids} returns the number of grids in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1036
1037
1038
1039
1040

@EndFunction
*/
int vlistNgrids(int vlistID)
{
1041
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1042

1043
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053

  return (vlistptr->ngrids);
}

/*
@Function  vlistNzaxis
@Title     Number of zaxis in a variable list

@Prototype int vlistNzaxis(int vlistID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1054
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1055
1056

@Description
1057
The function @func{vlistNzaxis} returns the number of zaxis in the variable list vlistID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1058
1059

@Result
1060
@func{vlistNzaxis} returns the number of zaxis in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1061
1062
1063
1064
1065

@EndFunction
*/
int vlistNzaxis(int vlistID)
{
1066
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1067

1068
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1069
1070
1071
1072
1073
1074
1075

  return (vlistptr->nzaxis);
}


void vlistDefNtsteps(int vlistID, int nts)
{
1076
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1077

1078
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1079

1080
  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
1081
    {
1082
      Warning("%s", "Operation not executed." );
1083
1084
1085
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1086
1087
1088
1089
1090
1091
  vlistptr->ntsteps = nts;
}


int vlistNtsteps(int vlistID)
{
1092
  vlist_t *vlistptr = vlist_to_pointer(vlistID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1093

Deike Kleberg's avatar