vlist.c 46.2 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
const resOps vlist_ops = {
77
  (valCompareFunc)vlist_compare,
78
  (valDestroyFunc)vlist_delete,
79
80
  (valPrintFunc)vlistPrintKernel
  , vlistGetSizeP,
81
82
  vlistPackP,
  vlistTxCode
83
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
84
85


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

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

110
static
111
vlist_t *vlist_new_entry(cdiResH resH)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
{
113
  vlist_t *vlistptr = xmalloc(sizeof(vlist_t));
114
  vlist_init_entry(vlistptr);
115
116
117
118
119
120
121
  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
122
123
124
  return (vlistptr);
}

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

  idx = vlistptr->self;

132
  reshRemove(idx, &vlist_ops );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
133
134
135
136

  free(vlistptr);

  if ( VLIST_Debug )
137
    Message("Removed idx %d from vlist list", idx);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
138
139
}

140
141
static
void vlist_initialize(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
142
143
144
145
146
{
  char *env;

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

152
153
static
void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
154
155
156
157
{
  int vlistID2;

  vlistID2 = vlistptr2->self;
158
  memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
159
  vlistptr2->atts.nelems = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
160
161
162
  vlistptr2->self = vlistID2;
}

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

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
176
177
178
179
180
181
182
183
184
185
@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();
186
varID = vlistDefVar(vlistID, gridID, zaxisID, TSTEP_INSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
187
188
189
190
191
192
   ...
streamDefVlist(streamID, vlistID);
   ...
vlistDestroy(vlistID);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
193
194
@EndFunction
*/
195
int vlistCreate(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
196
197
{
  int vlistID = 0;
198
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
199

200
201
  cdiInitialize();

202
  VLIST_INIT();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
203

204
  vlistptr = vlist_new_entry(CDI_UNDEFID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206
207
208
209
210

  vlistID = vlistptr->self;

  return (vlistID);
}

211
212
static void
vlist_delete(vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
213
{
214
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215

216
217
  int vlistID = vlistptr->self;

Deike Kleberg's avatar
Deike Kleberg committed
218
  vlistDelAtts(vlistID, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219

220
  int nvars = vlistptr->nvars;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
221

222
  for (int varID = 0; varID < nvars; varID++ )
Deike Kleberg's avatar
Deike Kleberg committed
223
224
225
226
227
228
    {
      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);
229
230

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

232
#if  defined  (HAVE_LIBGRIB_API)
233
234
235
236
237
238
239
240
241
      int i;
      for (i=0; i<vlistptr->vars[varID].opt_grib_int_nentries; i++) {
	if ( vlistptr->vars[varID].opt_grib_int_keyword[i] )
	  free(vlistptr->vars[varID].opt_grib_int_keyword[i]);
      }
      for (i=0; i<vlistptr->vars[varID].opt_grib_dbl_nentries; i++) {
	if ( vlistptr->vars[varID].opt_grib_dbl_keyword[i] )
	  free(vlistptr->vars[varID].opt_grib_dbl_keyword[i]);
      }
242
#endif
243

Deike Kleberg's avatar
Deike Kleberg committed
244
      vlistDelAtts(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
245
    }
246

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

Deike Kleberg's avatar
Deike Kleberg committed
249
  vlist_delete_entry(vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
250
251
}

252
253
254
255
256
257
258

/*
@Function  vlistDestroy
@Title     Destroy a variable list

@Prototype void vlistDestroy(int vlistID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
259
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}.
260
261
262
263
264
265
266
267
268
269
270
271

@EndFunction
*/
void vlistDestroy(int vlistID)
{
  vlist_t *vlistptr;

  vlistptr = vlist_to_pointer(vlistID);

  vlist_delete(vlistptr);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
272
273
274
275
276
277
/*
@Function  vlistCopy
@Title     Copy a variable list

@Prototype void vlistCopy(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
278
279
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
280
281

@Description
282
The function @func{vlistCopy} copies all entries from vlistID1 to vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
283
284
285
286
287

@EndFunction
*/
void vlistCopy(int vlistID2, int vlistID1)
{
288
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
289
290
291
292

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

293
294
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
295
296
297

  vlist_copy(vlistptr2, vlistptr1);

298
  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
299

Uwe Schulzweida's avatar
Uwe Schulzweida committed
300
301
302
  if ( vlistptr1->vars )
    {
      int nvars = vlistptr1->nvars;
303
      int varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
304

305
306
307
      //vlistptr2->varsAllocated = nvars;
      vlistptr2->vars = (var_t *) malloc(vlistptr2->varsAllocated*sizeof(var_t));
      memcpy(vlistptr2->vars, vlistptr1->vars, vlistptr2->varsAllocated*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
308
309

      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
310
311
312
        {
          if ( vlistptr1->vars[varID].name )
            vlistptr2->vars[varID].name = strdupx(vlistptr1->vars[varID].name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
313

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

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

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

323
324
325
326
327
328
          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));
            }
329
#if  defined  (HAVE_LIBGRIB_API)
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
          /* ---------------------------------- */
          /* Local change: 2013-01-28, FP (DWD) */
          /* ---------------------------------- */

	  int i;
	  vlistptr2->vars[varID].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[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];
	    }
	  }
	  vlistptr2->vars[varID].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[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];
	    }
	  }
349
#endif
350

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

354
355
          if ( vlistptr1->vars[varID].levinfo )
            {
356
              int nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
357
358
359
360
              vlistptr2->vars[varID].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
              memcpy(vlistptr2->vars[varID].levinfo,
                     vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
            }
361
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
362
363
364
365
366
367
368
369
370
    }
}

/*
@Function  vlistDuplicate
@Title     Duplicate a variable list

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

@Description
374
The function @func{vlistDuplicate} duplicates the variable list from vlistID1.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375
376

@Result
377
@func{vlistDuplicate} returns an identifier to the duplicated variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
378
379
380
381
382
383

@EndFunction
*/
int vlistDuplicate(int vlistID)
{
  int vlistIDnew;
384
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
386
387

  vlistptr = vlist_to_pointer(vlistID);

388
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
389

390
  vlistIDnew = vlistCreate();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
391
392
393
394
395
396
397
398
399
400

  vlistCopy(vlistIDnew, vlistID);

  return (vlistIDnew);
}


void vlistClearFlag(int vlistID)
{
  int varID, levID;
401
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
403
404
405
406
407

  vlistptr = vlist_to_pointer(vlistID);

  for ( varID = 0; varID < vlistptr->nvars; varID++ )
    {
      vlistptr->vars[varID].flag = FALSE;
408
      if ( vlistptr->vars[varID].levinfo )
409
410
411
412
413
414
415
        {
          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
416
417
418
    }
}

419
420
421
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
422
423
424
425
426
427
{
  int zaxisdefined;
  int nzaxis;
  int zaxisID = CDI_UNDEFID;
  int index;
  int zaxisglobdefined = 0;
428
  int has_bounds = FALSE;
429
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
430
431
432

  vlistptr = vlist_to_pointer(vlistID);

433
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
434
435
436
437

  zaxisdefined = 0;
  nzaxis = vlistptr->nzaxis;

438
439
440
  if ( lbounds && ubounds ) has_bounds = TRUE;

  for ( index = 0; index < nzaxis; ++index )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
442
443
    {
      zaxisID = vlistptr->zaxisIDs[index];

444
      if ( zaxisCompare(zaxisID, zaxistype, nlevels, has_bounds, levels, NULL, NULL, 0) == 0 )
Thomas Jahns's avatar
Thomas Jahns committed
445
446
447
448
        {
          zaxisdefined = 1;
          break;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
449
450
451
452
453
    }

  if ( ! zaxisdefined )
    {
      nzaxis = zaxisSize();
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
      if ( nzaxis > 0 )
        {
          int *zaxisIndexList;
          zaxisIndexList = (int *) malloc ( nzaxis * sizeof ( int ));
          zaxisGetIndexList ( nzaxis, zaxisIndexList );
          for ( index = 0; index < nzaxis; ++index )
            {
              zaxisID = zaxisIndexList[index];
              if ( zaxisCompare(zaxisID, zaxistype, nlevels, has_bounds, levels, NULL, NULL, 0) == 0 )
                {
                  zaxisglobdefined = 1;
                  break;
                }
            }
          if ( zaxisIndexList ) free ( zaxisIndexList );
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
470
471
472
473
474
    }

  if ( ! zaxisdefined )
    {
      if ( ! zaxisglobdefined )
475
476
477
	{
	  zaxisID = zaxisCreate(zaxistype, nlevels);
	  zaxisDefLevels(zaxisID, levels);
478
	  if ( has_bounds )
479
	    {
480
481
	      zaxisDefLbounds(zaxisID, lbounds);
	      zaxisDefUbounds(zaxisID, ubounds);
482
483
484
485
486
487
488
489
490
491
	    }

	  if ( zaxistype == ZAXIS_HYBRID )
	    {
	      if ( vctsize > 0 )
		zaxisDefVct(zaxisID, vctsize, vct);
	      else
		Warning("VCT missing");
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506

      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
507
508
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
509
510

@Description
511
The function @func{vlistCopyFlag} copies all entries with a flag from vlistID1 to vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
514
515
516

@EndFunction
*/
void vlistCopyFlag(int vlistID2, int vlistID1)
{
517
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
519
520
521

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

522
523
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524
525

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

527
  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528

Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
530
531
532
533
534
535
536
537
538
539
540
  if ( vlistptr1->vars )
    {
      int nvars = vlistptr1->nvars;
      int nvars2 = 0, levID2;
      int nlevs, nlevs2, levID, varID, varID2;
      int gridID, zaxisID;
      int index;

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

      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
541
        if ( vlistptr1->vars[varID].flag ) nvars2++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
543

      vlistptr2->nvars = nvars2;
544
      vlistptr2->varsAllocated = nvars2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
      if ( nvars2 > 0 )
Thomas Jahns's avatar
Thomas Jahns committed
546
        vlistptr2->vars  = (var_t *) malloc(nvars2*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
547
      else
Thomas Jahns's avatar
Thomas Jahns committed
548
        vlistptr2->vars  = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
549
550
551

      varID2 = 0;
      for ( varID = 0; varID < nvars; varID++ )
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
	if ( vlistptr1->vars[varID].flag )
	  {
	    vlistptr2->vars[varID2].flag = FALSE;
	    zaxisID = vlistptr1->vars[varID].zaxisID;
	    gridID  = vlistptr1->vars[varID].gridID;

	    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);

577
578
579
580
581
582
583
            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));
              }

584
#if  defined  (HAVE_LIBGRIB_API)
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
	    /* ---------------------------------- */
	    /* 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];
	      }
	    }
	    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];
	      }
	    }
604
#endif
605
606
607
608

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

609
	    nlevs  = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
610
	    nlevs2 = 0;
611
612
613
            if ( vlistptr1->vars[varID].levinfo )
              for ( levID = 0; levID < nlevs; levID++ )
                if ( vlistptr1->vars[varID].levinfo[levID].flag ) nlevs2++;
614
615
616
617
618
619
620
621
622

	    vlistptr2->vars[varID2].levinfo = (levinfo_t *) malloc(nlevs2*sizeof(levinfo_t));

	    if ( nlevs != nlevs2 )
	      {
		int zaxisType;
		int zaxisID2;
		int nvct = 0;
		double *levels;
623
		double *lbounds = NULL, *ubounds = NULL;
624
		const double *vct = NULL;
625
                char ctemp[CDI_MAX_NAME];
626
627
628
629

		zaxisID = vlistptr1->vars[varID].zaxisID;
		levels = (double *) malloc(nlevs2*sizeof(double));
		levID2 = 0;
630
631
                if (!vlistptr1->vars[varID].levinfo)
                  cdiVlistCreateVarLevInfo(vlistptr1, varID);
632
		for ( levID = 0; levID < nlevs; ++levID )
633
634
635
636
637
638
639
640
641
642
643
644
645
646
		  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);
		    }

		zaxisType = zaxisInqType(zaxisID);

		if ( zaxisType == ZAXIS_HYBRID )
		  {
		    nvct = zaxisInqVctSize(zaxisID);
		    vct  = zaxisInqVctPtr(zaxisID);
		  }
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673

                if ( zaxisInqLbounds(zaxisID, NULL) && zaxisInqUbounds(zaxisID, NULL) )
                  {
                    double *lbounds1, *ubounds1;
                    lbounds1 = (double *) malloc(nlevs*sizeof(double));
                    ubounds1 = (double *) malloc(nlevs*sizeof(double));

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

                    lbounds = (double *) malloc(nlevs2*sizeof(double));
                    ubounds = (double *) malloc(nlevs2*sizeof(double));

                    levID2 = 0;
                    for ( levID = 0; levID < nlevs; ++levID )
                      if ( vlistptr1->vars[varID].levinfo[levID].flag )
                        {
                          lbounds[levID2] = lbounds1[levID];
                          ubounds[levID2] = ubounds1[levID];
                          levID2++;
                        }

                    free(lbounds1);
                    free(ubounds1);
                  }

		zaxisID2 = vlist_generate_zaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, ubounds, nvct, vct);
674
		free(levels);
675
676
                if ( lbounds ) free(lbounds);
                if ( ubounds ) free(ubounds);
677

678
679
680
681
682
683
                zaxisInqName(zaxisID, ctemp);
                zaxisDefName(zaxisID2, ctemp);
                zaxisInqLongname(zaxisID, ctemp);
                zaxisDefLongname(zaxisID2, ctemp);
                zaxisInqUnits(zaxisID, ctemp);
                zaxisDefUnits(zaxisID2, ctemp);
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725

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

	    for ( levID = 0; levID < nlevs2; levID++ )
	      {
		vlistptr2->vars[varID2].levinfo[levID].flag  = FALSE;
		vlistptr2->vars[varID2].levinfo[levID].index = -1;
	      }

	    levID2 = 0;
	    for ( levID = 0; levID < nlevs; levID++ )
	      if ( vlistptr1->vars[varID].levinfo[levID].flag )
		{
		  vlistptr2->vars[varID2].levinfo[levID2].flevelID = levID;
		  vlistptr2->vars[varID2].levinfo[levID2].mlevelID = levID;
		  levID2++;
		}

	    for ( index = 0; index <vlistptr2->ngrids; index++ )
	      if (vlistptr2->gridIDs[index] == gridID ) break;

	    if ( index == vlistptr2->ngrids )
	      {
		vlistptr2->gridIDs[vlistptr2->ngrids++] = gridID;
		if (vlistptr2->ngrids >= MAX_GRIDS_PS )
		  Error("Internal Problem! More than %d grids.", MAX_GRIDS_PS);
	      }

	    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
726
727
728
729
730
731
732
733
734
    }
}

/*
@Function  vlistCat
@Title     Concatenate two variable lists

@Prototype void vlistCat(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
735
736
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
737
738
739
740
741
742
743
744
745
746
747

@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;
748
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
749
750
751
752

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

753
754
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
755
756
757
758
759
760

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

761
762
763
764
765
  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
766
  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars, nvars1*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
767
768
769
770
771
772
773

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

774
775
776
      vlistptr1->vars[varID].mvarID = varID2;
      vlistptr2->vars[varID2].mvarID = varID;

777
      if ( vlistptr1->vars[varID].param < 0 )
778
779
780
	{
	  int pnum, pcat, pdis;
	  cdiDecodeParam(vlistptr1->vars[varID].param, &pnum, &pcat, &pdis);
781
	  pnum = -(varID2+1);
782
783
	  vlistptr2->vars[varID2].param = cdiEncodeParam(pnum, pcat, pdis);
	}
784

Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
      if ( vlistptr1->vars[varID].name )
Thomas Jahns's avatar
Thomas Jahns committed
786
        vlistptr2->vars[varID2].name = strdupx(vlistptr1->vars[varID].name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
787
788

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

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

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

797
      nlevs = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
798
799
800
801
802
      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
803

804
805
806
807
808
809
      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));
        }

810
#if  defined  (HAVE_LIBGRIB_API)
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
      /* ---------------------------------- */
      /* 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];
	}
      }
      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];
	}
      }
830
#endif
831

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
835
836
      gridID = vlistptr1->vars[varID].gridID;
      for ( index = 0; index < vlistptr2->ngrids; index++ )
Thomas Jahns's avatar
Thomas Jahns committed
837
        if ( gridID == vlistptr2->gridIDs[index] ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
838
839

      if ( index == vlistptr2->ngrids )
840
841
842
843
844
	{
	  vlistptr2->gridIDs[vlistptr2->ngrids++] = gridID;
	  if ( vlistptr2->ngrids >= MAX_GRIDS_PS )
	    Error("Internal Problem! More than %d grids.", MAX_GRIDS_PS);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
847

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

      if ( index == vlistptr2->nzaxis )
851
852
853
854
855
	{
	  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
856
857
858
859
860
861
862
863
864
    }
}

/*
@Function  vlistMerge
@Title     Merge two variable lists

@Prototype void vlistMerge(int vlistID2, int vlistID1)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
865
866
    @Item  vlistID2  Target variable list ID.
    @Item  vlistID1  Source variable list ID.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
867
868

@Description
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
Merge the variable list vlistID1 to the variable list vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
870
871
872
873
874
875
876
877
878
879
880

@EndFunction
*/
void vlistMerge(int vlistID2, int vlistID1)
{
  int nvars1, nvars2;
  int varID = 0, varID2, levID, nlevs, nlevs1, nlevs2;
  int index, zaxisID;
  int zaxisID1, zaxisID2;
  int *lvar;
  double *levels;
881
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
883
884
885

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

886
887
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
888
889
890
891
892
893
894

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

  if ( nvars1 == nvars2 )
    {
      for ( varID = 0; varID < nvars2; varID++ )
895
896
897
898
899
900
901
902
903
904
905
906
	{
	  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
907
908
909
910
911
    }

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

Thomas Jahns's avatar
Thomas Jahns committed
916
917
          vlistptr1->vars[varID].mvarID = varID;
          vlistptr2->vars[varID].mvarID = varID;
918

919
920
          nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
          nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
921

Thomas Jahns's avatar
Thomas Jahns committed
922
          nlevs = nlevs1 + nlevs2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
923

Thomas Jahns's avatar
Thomas Jahns committed
924
925
926
          /*
          fprintf(stderr, "var %d %d %d %d %d\n", varID, nlevs1, nlevs2, nlevs, sizeof(levinfo_t));
          */
927
928
929
930
          if (vlistptr1->vars[varID].levinfo)
            {
              vlistptr2->vars[varID].levinfo =
                xrealloc(vlistptr2->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
931

932
933
934
935
936
              memcpy(vlistptr2->vars[varID].levinfo+nlevs2,
                     vlistptr1->vars[varID].levinfo, nlevs1*sizeof(levinfo_t));
            }
          else
            cdiVlistCreateVarLevInfo(vlistptr1, varID);
937
938
939
940
941
	  for ( levID = 0; levID < nlevs1; levID++ )
	    {
	      vlistptr1->vars[varID].levinfo[levID].mlevelID = nlevs2 + levID;
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942
943
944
945
946

      lvar = (int *) malloc(nvars2*sizeof(int));
      for ( varID = 0; varID < nvars2; varID++ ) lvar[varID] = FALSE;

      for ( varID = 0; varID < nvars2; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
947
948
949
950
951
952
        {
          if ( lvar[varID] == TRUE ) continue;

          zaxisID1 = vlistptr1->vars[varID].zaxisID;
          zaxisID2 = vlistptr2->vars[varID].zaxisID;
          /*
953
954
          nlevs1 = zaxisInqSize(vlistptr1->vars[varID].zaxisID);
          nlevs2 = zaxisInqSize(vlistptr2->vars[varID].zaxisID);
Thomas Jahns's avatar
Thomas Jahns 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
979
980
981
982
983
984
985
986
987
988
989
          */
          nlevs1 = zaxisInqSize(zaxisID1);
          nlevs2 = zaxisInqSize(zaxisID2);
          /*
          fprintf(stderr, "zaxis %d %d %d %d\n", zaxisID1, zaxisID2, nlevs1, nlevs2);
          */
          nlevs = nlevs1 + nlevs2;

          zaxisID = zaxisDuplicate(zaxisID2);

          zaxisResize(zaxisID, nlevs);

          levels = (double *) malloc(nlevs1*sizeof(double));

          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]);
          */
          for ( levID = 0; levID < nlevs1; levID++ )
            zaxisDefLevel(zaxisID, nlevs2+levID, levels[levID]);

          free(levels);

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

          for ( varID2 = 0; varID2 < nvars2; varID2++ )
            if ( lvar[varID2] == FALSE && vlistptr2->vars[varID2].zaxisID == zaxisID2 )
              {
                vlistptr2->vars[varID2].zaxisID = zaxisID;
                lvar[varID2] = TRUE;
              }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004

      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
1005
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1006
1007

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

@Result
1011
@func{vlistNvars} returns the number of variables in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1012
1013
1014
1015
1016

@EndFunction
*/
int vlistNvars(int vlistID)
{
1017
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1018
1019
1020

  vlistptr = vlist_to_pointer(vlistID);

1021
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1022
1023
1024
1025

  return (vlistptr->nvars);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1026

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1027
1028
1029
int vlistNrecs(int vlistID)
{
  int varID, nrecs = 0;
1030
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1031
1032
1033

  vlistptr = vlist_to_pointer(vlistID);

1034
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1035
1036

  for ( varID = 0; varID < vlistptr->nvars; varID++ )
1037
    nrecs +=  zaxisInqSize(vlistptr->vars[varID].zaxisID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1038
1039
1040
1041
1042

  return (nrecs);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
1043
1044
int vlistNumber(int vlistID)
{
1045
  int varID, number, number2, datatype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1046
1047
1048
1049
  vlist_t *vlistptr;

  vlistptr = vlist_to_pointer(vlistID);

1050
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1051

1052
1053
1054
1055
1056
1057
  datatype = vlistptr->vars[0].datatype;
  if (  datatype== DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
    number = CDI_COMP;
  else
    number = CDI_REAL;

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1058
  for ( varID = 1; varID < vlistptr->nvars; varID++ )
1059
1060
1061
    {
      datatype = vlistptr->vars[varID].datatype;
      if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
Thomas Jahns's avatar
Thomas Jahns committed
1062
        number2 = CDI_COMP;
1063
      else
Thomas Jahns's avatar
Thomas Jahns committed
1064
        number2 = CDI_REAL;
1065
1066

      if ( number2 != number )
Thomas Jahns's avatar
Thomas Jahns committed
1067
1068
1069
1070
        {
          number = CDI_BOTH;
          break;
        }
1071
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1072
1073
1074
1075

  return (number);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1076
1077
1078
1079
1080
1081
/*
@Function  vlistNgrids
@Title     Number of grids in a variable list

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

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

@Result
1088
@func{vlistNgrids} returns the number of grids in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1089
1090
1091
1092
1093

@EndFunction
*/
int vlistNgrids(int vlistID)
{
1094
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1095
1096
1097

  vlistptr = vlist_to_pointer(vlistID);

1098
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108

  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
1109
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate} or @fref{streamInqVlist}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1110
1111

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

@Result
1115
@func{vlistNzaxis} returns the number of zaxis in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1116
1117
1118
1119
1120

@EndFunction
*/
int vlistNzaxis(int vlistID)
{
1121
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1122
1123
1124

  vlistptr = vlist_to_pointer(vlistID);

1125
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1126
1127
1128
1129
1130
1131
1132

  return (vlistptr->nzaxis);
}


void vlistDefNtsteps(int vlistID, int nts)
{
1133
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1134
1135
1136

  vlistptr = vlist_to_pointer(vlistID);

1137
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1138

1139
  if ( reshGetStatus ( vlistID, &vlist_ops ) == RESH_CLOSED )
1140
    {
1141
      Warning("%s", "Operation not executed." );
1142
1143
1144
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1145
1146
1147
1148
1149
1150
  vlistptr->ntsteps = nts;
}


int vlistNtsteps(int vlistID)
{
1151
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1152
1153
1154

  vlistptr = vlist_to_pointer(vlistID);

1155
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1156
1157
1158
1159

  return (vlistptr->ntsteps);
}

1160
static void
1161
vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1162
{
1163
  int nvars, flag, index;
1164
  int varID, fvarID, mvarID, flevID, mlevID, levID;
1165
  int param, gridID, zaxisID, tsteptype, nlevs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1166
  int dtype;
1167

Thomas Jahns's avatar
Thomas Jahns committed
1168
  int iorank;
1169

1170
  char paramstr[32];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1171
1172
1173
  char *name, *longname, *units;
  double level;

1174
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1175

1176
  fprintf ( fp, "#\n# vlistID %d\n#\n", vlistptr->self);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1177
1178
1179

  nvars = vlistptr->nvars;

1180
1181
1182
1183
1184
1185
1186
  fprintf ( fp, "nvars   %d\n", nvars);
  fprintf ( fp, "ngrids  %d\n", vlistptr->ngrids);
  fprintf ( fp, "nzaxis  %d\n", vlistptr->nzaxis);
  fprintf ( fp, "taxisID %d\n", vlistptr->taxisID);
  fprintf ( fp, "instID  %d\n", vlistptr->instID);
  fprintf ( fp, "modelID %d\n", vlistptr->modelID);
  fprintf ( fp, "tableID %d\n", vlistptr->tableID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1187
1188
1189

  if ( nvars > 0 )
    {
1190
      fprintf(fp, " varID param    gridID zaxisID tsteptype flag "
1191
              " name     longname iorank\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1192
      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
1193
1194
1195
1196
        {
          param    = vlistptr->vars[varID].param;
          gridID   = vlistptr->vars[varID].gridID;
          zaxisID  = vlistptr->vars[varID].zaxisID;
1197
	  tsteptype= vlistptr->vars[varID].tsteptype;
Thomas Jahns's avatar
Thomas Jahns committed
1198
1199
1200
1201
          name     = vlistptr->vars[varID].name;
          longname = vlistptr->vars[varID].longname;
          units    = vlistptr->vars[varID].units;
          flag     = vlistptr->vars[varID].flag;
1202
          iorank   = vlistptr->vars[varID].iorank;
Thomas Jahns's avatar
Thomas Jahns committed
1203
1204

          cdiParamToString(param, paramstr, sizeof(paramstr));
1205
          fprintf(fp, "%6d %-8s %6d %6d %6d %5d %-8s"
1206
                  " %s %6d",
1207
                  varID, paramstr, gridID, zaxisID, tsteptype, flag,
1208
                  name ? name : "", longname ? longname : "",
1209
                  iorank);
1210

1211
1212
          if ( units ) fprintf ( fp, "   [%s]", units);
          fprintf ( fp, "\n");
Thomas Jahns's avatar
Thomas Jahns committed
1213
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1214

1215
1216
      fprintf(fp, "\n");
      fprintf(fp, " varID  levID fvarID flevID mvarID mlevID  index  dtype  flag  level\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1217
      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
1218
1219
        {
          zaxisID  = vlistptr->vars[varID].zaxisID;
1220
          nlevs    = zaxisInqSize(zaxisID);
Thomas Jahns's avatar
Thomas Jahns committed
1221
1222
1223
1224
1225
          fvarID   = vlistptr->vars[varID].fvarID;
          mvarID   = vlistptr->vars[varID].mvarID;
          dtype    = vlistptr->vars[varID].datatype;
          for ( levID = 0; levID < nlevs; levID++ )
            {
1226
1227
1228
1229
1230
1231
1232
1233
1234
              levinfo_t li;
              if (vlistptr->vars[varID].levinfo)
                li = vlistptr->vars[varID].levinfo[levID];
              else
                li = DEFAULT_LEVINFO(levID);
              flevID = li.flevelID;
              mlevID = li.mlevelID;
              index  =