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

#include "dmemory.h"
#include "cdi.h"
#include "stream_int.h"
#include "vlist.h"
#include "varscan.h"
10
#include "namespace.h"
11
#include "pio_util.h"
12
#include "resource_handle.h"
Thomas Jahns's avatar
Thomas Jahns committed
13
#include "vlist_var.h"
14
#include "vlist_att.h"
15
#include "pio_rpc.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
16

17
static int VLIST_Debug = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
18
19
20
21
22
23

static void vlist_initialize(void);

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

24
static pthread_once_t  _vlist_init_thread = PTHREAD_ONCE_INIT;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25

26
#  define VLIST_INIT()        \
27
  pthread_once(&_vlist_init_thread, vlist_initialize)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
28
29
30

#else

31
static int vlistIsInitialized = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
32

33
34
35
#  define VLIST_INIT()               \
  if ( _vlist_init == FALSE ) vlist_initialize()
#endif
Uwe Schulzweida's avatar
Uwe Schulzweida committed
36
37


38
39
40
/* FIXME: implementation incomplete, fix once leaf nodes are complete */
static int
vlist_compare(vlist_t *a, vlist_t *b)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
{
42
43
44
45
46
47
  int diff;
  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);
  return diff;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
48
49
}

50
static void
51
vlistPrintKernel(vlist_t *vlistptr, FILE * fp );
52
#ifdef USE_MPI
53
static int  vlistGetSizeP ( void * vlistptr, MPI_Comm comm );
54
55
static void vlistPackP    ( void * vlistptr, void * buff, int size,
                            int *position, MPI_Comm comm );
56
static int  vlistTxCode   ( void );
57
#endif
58

59
60
resOps vlist_ops = {
  (valCompareFunc)vlist_compare,
61
  free,
62
63
64
  (valPrintFunc)vlistPrintKernel
#ifdef USE_MPI
  , vlistGetSizeP,
65
66
  vlistPackP,
  vlistTxCode
67
#endif
68
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
69
70


71
vlist_t *vlist_to_pointer(int code)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
72
{
73
  VLIST_INIT();
74
  return reshGetVal(code, &vlist_ops );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
75
76
}

77
78
static
void vlist_init_entry(vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
79
{
80
  vlistptr->self           = reshPut(vlistptr, &vlist_ops);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
81
82
83
84
85

  vlistptr->nvars          = 0;
  vlistptr->vars           = NULL;
  vlistptr->ngrids         = 0;
  vlistptr->nzaxis         = 0;
86
  vlistptr->taxisID        = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87
88
89
90
91
  vlistptr->instID         = cdiDefaultInstID;
  vlistptr->modelID        = cdiDefaultModelID;
  vlistptr->tableID        = cdiDefaultTableID;
  vlistptr->varsAllocated  = 0;
  vlistptr->ntsteps        = CDI_UNDEFID;
92
  vlistptr->atts.nalloc    = MAX_ATTRIBUTES;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
  vlistptr->atts.nelems    = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
94
95
}

96
97
static
vlist_t *vlist_new_entry(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
98
{
99
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
100

101
  vlistptr = (vlist_t *)xmalloc(sizeof(vlist_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
102

103
  vlist_init_entry(vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
104
105
106
107

  return (vlistptr);
}

108
109
static
void vlist_delete_entry(vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
110
{
Thomas Jahns's avatar
Thomas Jahns committed
111
  int idx;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
113
114

  idx = vlistptr->self;

115
  reshRemove(idx, &vlist_ops );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
116
117
118
119

  free(vlistptr);

  if ( VLIST_Debug )
120
    Message("Removed idx %d from vlist list", idx);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
122
}

123
124
static
void vlist_initialize(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
125
126
127
128
129
130
131
{
  char *env;

  env = getenv("VLIST_DEBUG");
  if ( env ) VLIST_Debug = atoi(env);
}

132
133
static
void vlist_copy(vlist_t *vlistptr2, vlist_t *vlistptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
134
135
136
137
{
  int vlistID2;

  vlistID2 = vlistptr2->self;
138
  memcpy(vlistptr2, vlistptr1, sizeof(vlist_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
139
  vlistptr2->atts.nelems = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
140
141
142
  vlistptr2->self = vlistID2;
}

143
144
static
void vlist_check_ptr(const char *caller, vlist_t *vlistptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
145
146
{
  if ( vlistptr == NULL )
147
    Errorc("vlist undefined!");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148
149
150
}

/*
151
@Function  vlistCreate
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152
153
@Title     Create a variable list

154
@Prototype int vlistCreate(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
155

Uwe Schulzweida's avatar
Uwe Schulzweida committed
156
157
158
159
160
161
162
163
164
165
@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();
166
varID = vlistDefVar(vlistID, gridID, zaxisID, TSTEP_INSTANT);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167
168
169
170
171
172
   ...
streamDefVlist(streamID, vlistID);
   ...
vlistDestroy(vlistID);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
173
174
@EndFunction
*/
175
int vlistCreate(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
176
177
{
  int vlistID = 0;
178
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
179

180
  VLIST_INIT();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
181
182
183
184
185
186
187
188
189

  vlistptr = vlist_new_entry();

  vlistID = vlistptr->self;

  return (vlistID);
}

/*
190
@Function  vlistDestroy
191
@Title     Destroy a variable list
Uwe Schulzweida's avatar
Uwe Schulzweida committed
192

193
@Prototype void vlistDestroy(int vlistID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
194
@Parameter
195
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
196
197
198

@EndFunction
*/
199
void vlistDestroy(int vlistID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
200
{
201
  vlist_t *vlistptr;
Deike Kleberg's avatar
Deike Kleberg committed
202
203
  int nvars;
  int varID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
204
205
206

  vlistptr = vlist_to_pointer(vlistID);

207
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208

Deike Kleberg's avatar
Deike Kleberg committed
209
  vlistDelAtts(vlistID, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210

Deike Kleberg's avatar
Deike Kleberg committed
211
  nvars = vlistptr->nvars;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
212

Deike Kleberg's avatar
Deike Kleberg committed
213
214
215
216
217
218
219
  for ( varID = 0; varID < nvars; varID++ )
    {
      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);
220
221

      if ( vlistptr->vars[varID].ensdata )  free(vlistptr->vars[varID].ensdata);
Thomas Jahns's avatar
Thomas Jahns committed
222
      if ( vlistptr->vars[varID].deco )     free(vlistptr->vars[varID].deco);
Deike Kleberg's avatar
Deike Kleberg committed
223
      vlistDelAtts(vlistID, varID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
224
    }
225
 
Deike Kleberg's avatar
Deike Kleberg committed
226
  if ( vlistptr->vars ) free(vlistptr->vars);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
227

Deike Kleberg's avatar
Deike Kleberg committed
228
  vlist_delete_entry(vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
229
230
231
232
233
234
235
236
}

/*
@Function  vlistCopy
@Title     Copy a variable list

@Prototype void vlistCopy(int vlistID2, int vlistID1)
@Parameter
237
238
    @Item  vlistID2  Target variable list ID
    @Item  vlistID1  Source variable list ID
Uwe Schulzweida's avatar
Uwe Schulzweida committed
239
240

@Description
241
The function @func{vlistCopy} copies all entries from vlistID1 to vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
243
244
245
246

@EndFunction
*/
void vlistCopy(int vlistID2, int vlistID1)
{
247
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248
249
250
251

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

252
253
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
254
255
256

  vlist_copy(vlistptr2, vlistptr1);

257
  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
258

Uwe Schulzweida's avatar
Uwe Schulzweida committed
259
260
261
262
263
  if ( vlistptr1->vars )
    {
      int nvars = vlistptr1->nvars;
      int nlevs, varID;

264
265
266
      //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
267
268

      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
269
270
271
        {
          if ( vlistptr1->vars[varID].name )
            vlistptr2->vars[varID].name = strdupx(vlistptr1->vars[varID].name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
272

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

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

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

Thomas Jahns's avatar
Thomas Jahns committed
282
283
284
285
          nlevs = vlistptr1->vars[varID].nlevs;
          vlistptr2->vars[varID].levinfo = (levinfo_t *) malloc(nlevs*sizeof(levinfo_t));
          memcpy(vlistptr2->vars[varID].levinfo,
                 vlistptr1->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
286

287
288
289
290
291
292
293
          if ( vlistptr2->vars[varID].ensdata ) free(vlistptr2->vars[varID].ensdata);
          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));
            }
294
295
296
297
298
299
300
          if ( vlistptr1->vars[varID].deco )
            {
              size_t decoSize = (size_t)vlistptr1->vars[varID].decoSize;
              vlistptr2->vars[varID].deco = malloc(decoSize * sizeof (deco_t));
              memcpy(vlistptr2->vars[varID].deco, vlistptr1->vars[varID].deco,
                     decoSize * sizeof (deco_t));
            }
301
302
303
304

	  vlistptr2->vars[varID].atts.nelems = 0;
	  vlistCopyVarAtts(vlistID1, varID, vlistID2, varID);
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
305
306
307
308
309
310
311
312
313
    }
}

/*
@Function  vlistDuplicate
@Title     Duplicate a variable list

@Prototype int vlistDuplicate(int vlistID)
@Parameter
314
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
315
316

@Description
317
The function @func{vlistDuplicate} duplicates the variable list from vlistID1.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
318
319

@Result
320
@func{vlistDuplicate} returns an identifier to the duplicated variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
321
322
323
324
325
326

@EndFunction
*/
int vlistDuplicate(int vlistID)
{
  int vlistIDnew;
327
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
328
329
330

  vlistptr = vlist_to_pointer(vlistID);

331
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
332

333
  vlistIDnew = vlistCreate();
Uwe Schulzweida's avatar
Uwe Schulzweida committed
334
335
336

  vlistCopy(vlistIDnew, vlistID);

337
338
339
  if ( ! namespaceHasLocalFile ( namespaceGetActive ()))
    reshSetStatus ( vlistIDnew, &vlist_ops, SUSPENDED );

Uwe Schulzweida's avatar
Uwe Schulzweida committed
340
341
342
343
344
345
346
  return (vlistIDnew);
}


void vlistClearFlag(int vlistID)
{
  int varID, levID;
347
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
348
349
350
351
352
353
354

  vlistptr = vlist_to_pointer(vlistID);

  for ( varID = 0; varID < vlistptr->nvars; varID++ )
    {
      vlistptr->vars[varID].flag = FALSE;
      for ( levID = 0; levID < vlistptr->vars[varID].nlevs; levID++ )
Thomas Jahns's avatar
Thomas Jahns committed
355
356
357
        {
          vlistptr->vars[varID].levinfo[levID].flag = FALSE;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
358
359
360
361
    }
}


362
int vlistInqZaxis(int vlistID, int zaxistype, int nlevels, double *levels, int lbounds, double *levels2,
Thomas Jahns's avatar
Thomas Jahns committed
363
                  int vctsize, const double *vct)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
364
365
366
367
368
369
{
  int zaxisdefined;
  int nzaxis;
  int zaxisID = CDI_UNDEFID;
  int index;
  int zaxisglobdefined = 0;
370
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371
372
373

  vlistptr = vlist_to_pointer(vlistID);

374
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
375
376
377
378
379
380
381
382

  zaxisdefined = 0;
  nzaxis = vlistptr->nzaxis;

  for ( index = 0; index < nzaxis; index++ )
    {
      zaxisID = vlistptr->zaxisIDs[index];

383
      if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, NULL, NULL, 0) == 0 )
Thomas Jahns's avatar
Thomas Jahns committed
384
385
386
387
        {
          zaxisdefined = 1;
          break;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
389
390
391
392
393
    }

  if ( ! zaxisdefined )
    {
      nzaxis = zaxisSize();
      for ( zaxisID = 0; zaxisID < nzaxis; zaxisID++ )
Thomas Jahns's avatar
Thomas Jahns committed
394
395
396
397
398
        if ( zaxisCompare(zaxisID, zaxistype, nlevels, lbounds, levels, NULL, NULL, 0) == 0 )
          {
            zaxisglobdefined = 1;
            break;
          }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
399
400
401
402
403
    }

  if ( ! zaxisdefined )
    {
      if ( ! zaxisglobdefined )
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
	{
	  zaxisID = zaxisCreate(zaxistype, nlevels);
	  zaxisDefLevels(zaxisID, levels);
	  if ( lbounds )
	    {
	      zaxisDefLbounds(zaxisID, levels);
	      zaxisDefUbounds(zaxisID, levels2);
	    }

	  if ( zaxistype == ZAXIS_HYBRID )
	    {
	      if ( vctsize > 0 )
		zaxisDefVct(zaxisID, vctsize, vct);
	      else
		Warning("VCT missing");
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435

      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
436
437
    @Item  vlistID2  Target variable list ID
    @Item  vlistID1  Source variable list ID
Uwe Schulzweida's avatar
Uwe Schulzweida committed
438
439

@Description
440
The function @func{vlistCopyFlag} copies all entries with a flag from vlistID1 to vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
441
442
443
444
445

@EndFunction
*/
void vlistCopyFlag(int vlistID2, int vlistID1)
{
446
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
447
448
449
450

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

451
452
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
454

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

456
  vlistCopyVarAtts(vlistID1, CDI_GLOBAL, vlistID2, CDI_GLOBAL);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
457

Uwe Schulzweida's avatar
Uwe Schulzweida committed
458
459
460
461
462
463
464
465
466
467
468
469
  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
470
        if ( vlistptr1->vars[varID].flag ) nvars2++;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
471
472

      vlistptr2->nvars = nvars2;
473
      vlistptr2->varsAllocated = nvars2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
474
      if ( nvars2 > 0 )
Thomas Jahns's avatar
Thomas Jahns committed
475
        vlistptr2->vars  = (var_t *) malloc(nvars2*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
476
      else
Thomas Jahns's avatar
Thomas Jahns committed
477
        vlistptr2->vars  = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
478
479
480

      varID2 = 0;
      for ( varID = 0; varID < nvars; varID++ )
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
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
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
	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);

	    nlevs  = vlistptr1->vars[varID].nlevs;
	    nlevs2 = 0;
	    for ( levID = 0; levID < nlevs; levID++ )
	      if ( vlistptr1->vars[varID].levinfo[levID].flag ) nlevs2++;

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

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

	    if ( nlevs != nlevs2 )
	      {
		int zaxisType;
		int zaxisID2;
		int nvct = 0;
		int lbounds;
		double *levels;
		double *levels2;
		const double *vct = NULL;

		zaxisID = vlistptr1->vars[varID].zaxisID;
		levels = (double *) malloc(nlevs2*sizeof(double));
		levID2 = 0;
		for ( 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);
		    }

		zaxisType = zaxisInqType(zaxisID);

		if ( zaxisType == ZAXIS_HYBRID )
		  {
		    nvct = zaxisInqVctSize(zaxisID);
		    vct  = zaxisInqVctPtr(zaxisID);
		  }
		lbounds  = 0;     /* <------------ have to defined */
		levels2  = NULL;  /* <------------ have to defined */
		zaxisID2 = vlistInqZaxis(vlistID2, zaxisType, nlevs2, levels, lbounds, levels2, nvct, vct);
		free(levels);

		{
		  char ctemp[256];
		  zaxisInqName(zaxisID, ctemp);
		  zaxisDefName(zaxisID2, ctemp);
		  zaxisInqLongname(zaxisID, ctemp);
		  zaxisDefLongname(zaxisID2, ctemp);
		  zaxisInqUnits(zaxisID, ctemp);
		  zaxisDefUnits(zaxisID2, ctemp);
		}

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

	    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
601
602
603
604
605
606
607
608
609
    }
}

/*
@Function  vlistCat
@Title     Concatenate two variable lists

@Prototype void vlistCat(int vlistID2, int vlistID1)
@Parameter
610
611
    @Item  vlistID2  Target variable list ID
    @Item  vlistID1  Source variable list ID
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
613
614
615
616
617
618
619
620
621
622

@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;
623
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
624
625
626
627

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

628
629
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
630
631
632
633
634
635

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

636
637
638
639
640
  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
641
  memcpy(vlistptr2->vars+nvars2, vlistptr1->vars, nvars1*sizeof(var_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
642
643
644
645
646
647
648

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

649
650
651
      vlistptr1->vars[varID].mvarID = varID2;
      vlistptr2->vars[varID2].mvarID = varID;

652
      if ( vlistptr1->vars[varID].param < 0 )
653
654
655
656
657
658
	{
	  int pnum, pcat, pdis;
	  cdiDecodeParam(vlistptr1->vars[varID].param, &pnum, &pcat, &pdis);
	  pnum=-(varID2+1);
	  vlistptr2->vars[varID2].param = cdiEncodeParam(pnum, pcat, pdis);
	}
659

Uwe Schulzweida's avatar
Uwe Schulzweida committed
660
      if ( vlistptr1->vars[varID].name )
Thomas Jahns's avatar
Thomas Jahns committed
661
        vlistptr2->vars[varID2].name = strdupx(vlistptr1->vars[varID].name);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
663

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

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

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

      nlevs = vlistptr1->vars[varID].nlevs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
673
674
      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
675

676
677
678
679
680
681
      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));
        }

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
686
      gridID = vlistptr1->vars[varID].gridID;
      for ( index = 0; index < vlistptr2->ngrids; index++ )
Thomas Jahns's avatar
Thomas Jahns committed
687
        if ( gridID == vlistptr2->gridIDs[index] ) break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
688
689

      if ( index == vlistptr2->ngrids )
690
691
692
693
694
	{
	  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
695
696
697

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

      if ( index == vlistptr2->nzaxis )
701
702
703
704
705
	{
	  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
706
707
708
709
710
711
712
713
714
    }
}

/*
@Function  vlistMerge
@Title     Merge two variable lists

@Prototype void vlistMerge(int vlistID2, int vlistID1)
@Parameter
715
716
    @Item  vlistID2  Target variable list ID
    @Item  vlistID1  Source variable list ID
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
718

@Description
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
Merge the variable list vlistID1 to the variable list vlistID2.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
720
721
722
723
724
725
726
727
728
729
730

@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;
731
  vlist_t *vlistptr1, *vlistptr2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
732
733
734
735

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

736
737
  vlist_check_ptr(__func__, vlistptr1);
  vlist_check_ptr(__func__, vlistptr2);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
739
740
741
742
743
744

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

  if ( nvars1 == nvars2 )
    {
      for ( varID = 0; varID < nvars2; varID++ )
745
746
747
748
749
750
751
752
753
754
755
756
	{
	  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
757
758
759
760
761
    }

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

Thomas Jahns's avatar
Thomas Jahns committed
766
767
          vlistptr1->vars[varID].mvarID = varID;
          vlistptr2->vars[varID].mvarID = varID;
768

Thomas Jahns's avatar
Thomas Jahns committed
769
770
          nlevs1 = vlistptr1->vars[varID].nlevs;
          nlevs2 = vlistptr2->vars[varID].nlevs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
771

Thomas Jahns's avatar
Thomas Jahns committed
772
          nlevs = nlevs1 + nlevs2;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773

Thomas Jahns's avatar
Thomas Jahns committed
774
775
776
777
778
779
          vlistptr2->vars[varID].nlevs = nlevs;
          /*
          fprintf(stderr, "var %d %d %d %d %d\n", varID, nlevs1, nlevs2, nlevs, sizeof(levinfo_t));
          */
          vlistptr2->vars[varID].levinfo =
            (levinfo_t *) realloc(vlistptr2->vars[varID].levinfo, nlevs*sizeof(levinfo_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
780

781
782
	  memcpy(vlistptr2->vars[varID].levinfo+nlevs2,
		 vlistptr1->vars[varID].levinfo, nlevs1*sizeof(levinfo_t));
783

784
785
786
787
788
	  for ( levID = 0; levID < nlevs1; levID++ )
	    {
	      vlistptr1->vars[varID].levinfo[levID].mlevelID = nlevs2 + levID;
	    }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
790
791
792
793

      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
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
        {
          if ( lvar[varID] == TRUE ) continue;

          zaxisID1 = vlistptr1->vars[varID].zaxisID;
          zaxisID2 = vlistptr2->vars[varID].zaxisID;
          /*
          nlevs1 = vlistptr1->vars[varID].nlevs;
          nlevs2 = vlistptr2->vars[varID].nlevs;
          */
          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
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

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

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

@Prototype int vlistNvars(int vlistID)
@Parameter
852
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
854

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

@Result
858
@func{vlistNvars} returns the number of variables in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
860
861
862
863

@EndFunction
*/
int vlistNvars(int vlistID)
{
864
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
865
866
867

  vlistptr = vlist_to_pointer(vlistID);

868
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
870
871
872

  return (vlistptr->nvars);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
873

Uwe Schulzweida's avatar
Uwe Schulzweida committed
874
875
876
int vlistNrecs(int vlistID)
{
  int varID, nrecs = 0;
877
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
879
880

  vlistptr = vlist_to_pointer(vlistID);

881
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
883
884
885
886
887
888
889

  for ( varID = 0; varID < vlistptr->nvars; varID++ )
    nrecs +=  vlistptr->vars[varID].nlevs;

  return (nrecs);
}


Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
891
int vlistNumber(int vlistID)
{
892
  int varID, number, number2, datatype;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
893
894
895
896
  vlist_t *vlistptr;

  vlistptr = vlist_to_pointer(vlistID);

897
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898

899
900
901
902
903
904
  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
905
  for ( varID = 1; varID < vlistptr->nvars; varID++ )
906
907
908
    {
      datatype = vlistptr->vars[varID].datatype;
      if ( datatype == DATATYPE_CPX32 || datatype == DATATYPE_CPX64 )
Thomas Jahns's avatar
Thomas Jahns committed
909
        number2 = CDI_COMP;
910
      else
Thomas Jahns's avatar
Thomas Jahns committed
911
        number2 = CDI_REAL;
912
913

      if ( number2 != number )
Thomas Jahns's avatar
Thomas Jahns committed
914
915
916
917
        {
          number = CDI_BOTH;
          break;
        }
918
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
920
921
922

  return (number);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
923
924
925
926
927
928
/*
@Function  vlistNgrids
@Title     Number of grids in a variable list

@Prototype int vlistNgrids(int vlistID)
@Parameter
929
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
930
931

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

@Result
935
@func{vlistNgrids} returns the number of grids in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
936
937
938
939
940

@EndFunction
*/
int vlistNgrids(int vlistID)
{
941
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942
943
944

  vlistptr = vlist_to_pointer(vlistID);

945
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
946
947
948
949
950
951
952
953
954
955

  return (vlistptr->ngrids);
}

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

@Prototype int vlistNzaxis(int vlistID)
@Parameter
956
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
957
958

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

@Result
962
@func{vlistNzaxis} returns the number of zaxis in a variable list.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
963
964
965
966
967

@EndFunction
*/
int vlistNzaxis(int vlistID)
{
968
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
969
970
971

  vlistptr = vlist_to_pointer(vlistID);

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

  return (vlistptr->nzaxis);
}


void vlistDefNtsteps(int vlistID, int nts)
{
980
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
981
982
983

  vlistptr = vlist_to_pointer(vlistID);

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

986
987
  if ( reshGetStatus ( vlistID, &vlist_ops ) == CLOSED )
    {
988
      xwarning("%s", "Operation not executed." );
989
990
991
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
992
993
994
995
996
997
  vlistptr->ntsteps = nts;
}


int vlistNtsteps(int vlistID)
{
998
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
999
1000
1001

  vlistptr = vlist_to_pointer(vlistID);

1002
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1003
1004
1005
1006

  return (vlistptr->ntsteps);
}

1007
static void
1008
vlistPrintKernel(vlist_t *vlistptr, FILE * fp )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1009
{
1010
  int nvars, flag, index;
1011
  int varID, fvarID, mvarID, flevID, mlevID, levID;
1012
  int param, gridID, zaxisID, tsteptype, nlevs;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1013
  int dtype;
1014
1015
1016

  int i, iorank, decoSize, size, rank, offset, chunk;

1017
  char paramstr[32];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1018
1019
1020
  char *name, *longname, *units;
  double level;

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

1023
  fprintf ( fp, "#\n# vlistID %d\n#\n", vlistptr->self);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1024
1025
1026

  nvars = vlistptr->nvars;

1027
1028
1029
1030
1031
1032
1033
  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
1034
1035
1036

  if ( nvars > 0 )
    {
1037
1038
      fprintf(fp, " varID param    gridID zaxisID tsteptype nlevel flag "
              " name     longname iorank decosize\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1039
      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
1040
1041
1042
1043
        {
          param    = vlistptr->vars[varID].param;
          gridID   = vlistptr->vars[varID].gridID;
          zaxisID  = vlistptr->vars[varID].zaxisID;
1044
	  tsteptype= vlistptr->vars[varID].tsteptype;
Thomas Jahns's avatar
Thomas Jahns committed
1045
1046
1047
1048
1049
          nlevs    = vlistptr->vars[varID].nlevs;
          name     = vlistptr->vars[varID].name;
          longname = vlistptr->vars[varID].longname;
          units    = vlistptr->vars[varID].units;
          flag     = vlistptr->vars[varID].flag;
1050
          iorank   = vlistptr->vars[varID].iorank;
1051
          decoSize = vlistptr->vars[varID].decoSize;
Thomas Jahns's avatar
Thomas Jahns committed
1052
1053

          cdiParamToString(param, paramstr, sizeof(paramstr));
1054
1055
1056
1057
1058
          fprintf(fp, "%6d %-8s %6d %6d %6d %6d %5d %-8s"
                  " %s %6d %6d",
                  varID, paramstr, gridID, zaxisID, tsteptype, nlevs, flag,
                  name ? name : "", longname ? longname : "",
                  iorank, decoSize);
1059

1060
1061
          if ( units ) fprintf ( fp, "   [%s]", units);
          fprintf ( fp, "\n");
Thomas Jahns's avatar
Thomas Jahns committed
1062
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1063

1064
1065
      fprintf(fp, "\n");
      fprintf(fp, " varID  levID fvarID flevID mvarID mlevID  index  dtype  flag  level\n");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1066
      for ( varID = 0; varID < nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
        {
          nlevs    = vlistptr->vars[varID].nlevs;
          zaxisID  = vlistptr->vars[varID].zaxisID;
          fvarID   = vlistptr->vars[varID].fvarID;
          mvarID   = vlistptr->vars[varID].mvarID;
          dtype    = vlistptr->vars[varID].datatype;
          for ( levID = 0; levID < nlevs; levID++ )
            {
              flevID = vlistptr->vars[varID].levinfo[levID].flevelID;
              mlevID = vlistptr->vars[varID].levinfo[levID].mlevelID;
              index  = vlistptr->vars[varID].levinfo[levID].index;
              flag   = vlistptr->vars[varID].levinfo[levID].flag;
              level  = zaxisInqLevel(zaxisID, levID);
1080
1081
1082
              fprintf(fp, "%6d %6d %6d %6d %6d %6d %6d %6d %5d  %.9g\n",
                      varID, levID, fvarID, flevID, mvarID, mlevID, index,
                      dtype, flag, level);
Thomas Jahns's avatar
Thomas Jahns committed
1083
1084
            }
        }
1085

1086
1087
      fprintf(fp, "\n");
      fprintf(fp, " varID  size iorank decosize corank offset  chunk\n");
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
      for ( varID = 0; varID < nvars; varID++ )
        {
          iorank    = vlistptr->vars[varID].iorank;
          decoSize  = vlistptr->vars[varID].decoSize;
          size      = vlistptr->vars[varID].nlevs *
            gridInqSize ( vlistptr->vars[varID].gridID );
          
          for ( i = 0; i < decoSize; i++ )
            {
              rank   = vlistptr->vars[varID].deco[i].rank;
              offset = vlistptr->vars[varID].deco[i].offset;
              chunk  = vlistptr->vars[varID].deco[i].chunk;
              fprintf ( fp, "%3d %8d %6d %6d %6d %8d %6d\n",
                        varID, size, iorank, decoSize, rank, offset, chunk );
            }
        }      
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1104
1105
1106
    }
}

1107
1108
1109
1110
1111
1112
1113
1114
1115

void vlistPrint(int vlistID)
{
  vlist_t *vlistptr;

  if ( vlistID == CDI_UNDEFID ) return;

  vlistptr = vlist_to_pointer(vlistID);
  vlist_check_ptr(__func__, vlistptr);
1116
  vlistPrintKernel(vlistptr, stdout);
1117
1118
}

1119
1120
1121
1122
1123
1124
1125
/*
@Function  vlistDefTaxis
@Title     Define the time axis

@Prototype void vlistDefTaxis(int vlistID, int taxisID)
@Parameter
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1126
    @Item  taxisID  Time axis ID, from a previous call to @fref{taxisCreate}
1127
1128
1129
1130
1131
1132

@Description
The function @func{vlistDefTaxis} defines the time axis of a variable list.

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1133
1134
void vlistDefTaxis(int vlistID, int taxisID)
{
1135
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1136
1137
1138

  vlistptr = vlist_to_pointer(vlistID);

1139
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1140

1141
1142
  if ( reshGetStatus ( vlistID, &vlist_ops ) == CLOSED )
    {
1143
      xwarning("%s", "Operation not executed." );
1144
1145
1146
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1147
1148
1149
  vlistptr->taxisID = taxisID;
}

1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
/*
@Function  vlistInqTaxis
@Title     Get the time axis

@Prototype int vlistInqTaxis(int vlistID)
@Parameter
    @Item  vlistID  Variable list ID, from a previous call to @fref{vlistCreate}

@Description
The function @func{vlistInqTaxis} returns the time axis of a variable list.

@Result
@func{vlistInqTaxis} returns an identifier to the time axis.

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1166
1167
int vlistInqTaxis(int vlistID)
{
1168
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1169
1170
1171

  vlistptr = vlist_to_pointer(vlistID);

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

  return (vlistptr->taxisID);
}

1177

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1178
1179
void  vlistDefTable(int vlistID, int tableID)
{
1180
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1181
1182
1183

  vlistptr = vlist_to_pointer(vlistID);

1184
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1185

1186
1187
  if ( reshGetStatus ( vlistID, &vlist_ops ) == CLOSED )
    {
1188
      xwarning("%s", "Operation not executed." );
1189
1190
1191
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1192
1193
1194
  vlistptr->tableID = tableID;
}

1195

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1196
1197
int vlistInqTable(int vlistID)
{
1198
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1199
1200
1201

  vlistptr = vlist_to_pointer(vlistID);

1202
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1203
1204
1205
1206

  return (vlistptr->tableID);
}

1207

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1208
1209
void vlistDefInstitut(int vlistID, int instID)
{
1210
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1211
1212
1213

  vlistptr = vlist_to_pointer(vlistID);

1214
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1215

1216
1217
  if ( reshGetStatus ( vlistID, &vlist_ops ) == CLOSED )
    {
1218
      xwarning("%s", "Operation not executed." );
Deike Kleberg's avatar
Deike Kleberg committed
1219

1220
      xdebug("%s", "");
1221
1222
1223
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1224
1225
1226
  vlistptr->instID = instID;
}

1227

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1228
1229
1230
int vlistInqInstitut(int vlistID)
{
  int varID, instID;
1231
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1232
1233
1234

  vlistptr = vlist_to_pointer(vlistID);

1235
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1236
1237
1238
1239
1240
1241
1242
1243

  instID = vlistptr->instID;

  if ( instID == CDI_UNDEFID )
    {
      instID  = vlistInqVarInstitut(vlistID, 0);

      for ( varID = 1; varID < vlistptr->nvars; varID++ )
Thomas Jahns's avatar
Thomas Jahns committed
1244
1245
1246
1247
        if ( instID != vlistInqVarInstitut(vlistID, varID) )
          {
            instID = CDI_UNDEFID;
            break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1248
1249
1250
1251
1252
1253
1254
      }
      vlistDefInstitut(vlistID, instID);
    }

  return (instID);
}

1255

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1256
1257
void vlistDefModel(int vlistID, int modelID)
{
1258
  vlist_t *vlistptr;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1259
1260
1261

  vlistptr = vlist_to_pointer(vlistID);

1262
  vlist_check_ptr(__func__, vlistptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1263

1264
1265
  if ( reshGetStatus ( vlistID, &vlist_ops ) == CLOSED )
    {
1266
      xwarning("%s", "Operation not executed." );
1267
1268
1269
      return;
    }

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1270
1271
1272
  vlistptr->modelID = modelID;
}

1273

Uwe Schulzweida's avatar
Uwe Schulzweida committed
1274
1275
1276
int vlistInqModel(int vlistID)
{
  int varID, modelID;
Uwe Schulzweida's avatar