1 #include <string.h>
2 #include <math.h>
3 #include <float.h>
4 
5 #include "dmemory.h"
6 
7 #include "cdi.h"
8 #include "cdi_cksum.h"
9 #include "cdi_int.h"
10 #include "cdi_uuid.h"
11 #include "resource_handle.h"
12 #include "resource_unpack.h"
13 #include "namespace.h"
14 #include "serialize.h"
15 #include "zaxis.h"
16 
17 #define  LevelUp    1
18 #define  LevelDown  2
19 
20 
21 static const struct {
22   unsigned char positive;   // 1: up;  2: down
23   const char *name;
24   const char *longname;
25   const char *stdname;
26   const char *units;
27 }
28 ZaxistypeEntry[] = {
29   { /*  0 */ 0, "sfc",               "surface",                "",               ""},
30   { /*  1 */ 0, "lev",               "generic",                "",               ""},
31   { /*  2 */ 2, "lev",               "hybrid",                 "",               "level"},
32   { /*  3 */ 2, "lev",               "hybrid_half",            "",               "level"},
33   { /*  4 */ 2, "plev",              "pressure",               "air_pressure",   "Pa"},
34   { /*  5 */ 1, "height",            "height",                 "height",         "m"},
35   { /*  6 */ 2, "depth",             "depth_below_sea",        "depth",          "m"},
36   { /*  7 */ 2, "depth",             "depth_below_land",       "",               "cm"},
37   { /*  8 */ 0, "lev",               "isentropic",             "",               "K"},
38   { /*  9 */ 0, "lev",               "trajectory",             "",               ""},
39   { /* 10 */ 1, "alt",               "altitude",               "",               "m"},
40   { /* 11 */ 0, "lev",               "sigma",                  "",               "level"},
41   { /* 12 */ 0, "lev",               "meansea",                "",               "level"},
42   { /* 13 */ 0, "toa",               "top_of_atmosphere",      "",               ""},
43   { /* 14 */ 0, "seabottom",         "sea_bottom",             "",               ""},
44   { /* 15 */ 0, "atmosphere",        "atmosphere",             "",               ""},
45   { /* 16 */ 0, "cloudbase",         "cloud_base",             "",               ""},
46   { /* 17 */ 0, "cloudtop",          "cloud_top",              "",               ""},
47   { /* 18 */ 0, "isotherm0",         "isotherm_zero",          "",               ""},
48   { /* 19 */ 0, "snow",              "snow",                   "",               ""},
49   { /* 20 */ 0, "lakebottom",        "lake_bottom",            "",               ""},
50   { /* 21 */ 0, "sedimentbottom",    "sediment_bottom",        "",               ""},
51   { /* 22 */ 0, "sedimentbottomta",  "sediment_bottom_ta",     "",               ""},
52   { /* 23 */ 0, "sedimentbottomtw",  "sediment_bottom_tw",     "",               ""},
53   { /* 24 */ 0, "mixlayer",          "mix_layer",              "",               ""},
54   { /* 25 */ 0, "height",            "generalized_height",     "height",         ""},
55   { /* 26 */ 0, "character",         "area_type",              "",               ""},
56   { /* 27 */ 0, "tropopause",        "tropopause",             "",               ""},
57 };
58 
59 enum {
60   CDI_NumZaxistype = sizeof(ZaxistypeEntry) / sizeof(ZaxistypeEntry[0]),
61 };
62 
63 
64 static int    zaxisCompareP    (zaxis_t *z1, zaxis_t *z2);
65 static void   zaxisDestroyP    (void *zaxisptr);
66 static void   zaxisPrintP      (void *zaxisptr, FILE *fp);
67 static int    zaxisGetPackSize (void *zaxisptr, void *context);
68 static void   zaxisPack        (void *zaxisptr, void *buffer, int size, int *pos, void *context);
69 static int    zaxisTxCode      (void);
70 
71 static const resOps zaxisOps = {
72   (int (*)(void *, void *))zaxisCompareP,
73   zaxisDestroyP,
74   zaxisPrintP,
75   zaxisGetPackSize,
76   zaxisPack,
77   zaxisTxCode
78 };
79 
getZaxisOps(void)80 const resOps *getZaxisOps(void)
81 {
82   return &zaxisOps;
83 }
84 
85 static int  ZAXIS_Debug = 0;   /* If set to 1, debugging */
86 
zaxisGetTypeDescription(int zaxisType,int * outPositive,const char ** outName,const char ** outLongName,const char ** outStdName,const char ** outUnit)87 void zaxisGetTypeDescription(int zaxisType, int *outPositive, const char **outName, const char **outLongName, const char **outStdName, const char **outUnit)
88 {
89   if ( zaxisType < 0 || zaxisType >= CDI_NumZaxistype )
90     {
91       if (outPositive) *outPositive = 0;
92       if (outName) *outName = NULL;
93       if (outLongName) *outLongName = NULL;
94       if (outStdName) *outStdName = NULL;
95       if (outUnit) *outUnit = NULL;
96     }
97   else
98     {
99       if (outPositive) *outPositive = ZaxistypeEntry[zaxisType].positive;
100       if (outName) *outName = ZaxistypeEntry[zaxisType].name;
101       if (outLongName && zaxisType != ZAXIS_GENERIC) *outLongName = ZaxistypeEntry[zaxisType].longname;
102       if (outStdName) *outStdName = ZaxistypeEntry[zaxisType].stdname;
103       if (outUnit) *outUnit = ZaxistypeEntry[zaxisType].units;
104     }
105 }
106 
107 
zaxis_to_pointer(int id)108 zaxis_t *zaxis_to_pointer(int id)
109 {
110   return (zaxis_t *)reshGetVal(id, &zaxisOps);
111 }
112 
113 static
zaxis_init(zaxis_t * zaxisptr)114 void zaxis_init(zaxis_t *zaxisptr)
115 {
116   zaxisptr->self           = CDI_UNDEFID;
117   zaxisptr->vals           = NULL;
118 #ifndef USE_MPI
119   zaxisptr->cvals          = NULL;
120   zaxisptr->clength        = 0;
121 #endif
122   zaxisptr->ubounds        = NULL;
123   zaxisptr->lbounds        = NULL;
124   zaxisptr->weights        = NULL;
125   zaxisptr->type           = CDI_UNDEFID;
126   zaxisptr->positive       = 0;
127   zaxisptr->scalar         = 0;
128   zaxisptr->direction      = 0;
129   zaxisptr->size           = 0;
130   zaxisptr->vctsize        = 0;
131   zaxisptr->vct            = NULL;
132 
133   cdiInitKeys(&zaxisptr->keys);
134   zaxisptr->atts.nalloc    = MAX_ATTRIBUTES;
135   zaxisptr->atts.nelems    = 0;
136 
137   cdiDefVarKeyInt(&zaxisptr->keys, CDI_KEY_DATATYPE, CDI_DATATYPE_FLT64);
138 }
139 
140 static
zaxisNewEntry(int id)141 zaxis_t *zaxisNewEntry(int id)
142 {
143   zaxis_t *zaxisptr = (zaxis_t *) Malloc(sizeof(zaxis_t));
144   zaxis_init(zaxisptr);
145 
146   if ( id == CDI_UNDEFID )
147     zaxisptr->self = reshPut(zaxisptr, &zaxisOps);
148   else
149     {
150       zaxisptr->self = id;
151       reshReplace(id, zaxisptr, &zaxisOps);
152     }
153 
154   return zaxisptr;
155 }
156 
157 static
zaxisInit(void)158 void zaxisInit(void)
159 {
160   static bool zaxisInitialized = false;
161   if ( zaxisInitialized ) return;
162   zaxisInitialized = true;
163 
164   const char *env = getenv("ZAXIS_DEBUG");
165   if ( env ) ZAXIS_Debug = atoi(env);
166 }
167 
168 static
zaxis_copy(zaxis_t * zaxisptr2,zaxis_t * zaxisptr1)169 void zaxis_copy(zaxis_t *zaxisptr2, zaxis_t *zaxisptr1)
170 {
171   const int zaxisID2 = zaxisptr2->self;
172   memcpy(zaxisptr2, zaxisptr1, sizeof(zaxis_t));
173   zaxisptr2->self = zaxisID2;
174   cdiInitKeys(&zaxisptr2->keys);
175   cdiCopyVarKeys(&zaxisptr1->keys, &zaxisptr2->keys);
176 }
177 
178 
cdiZaxisCount(void)179 unsigned cdiZaxisCount(void)
180 {
181   return reshCountType(&zaxisOps);
182 }
183 
184 static
zaxisCreate_(int zaxistype,int size,int id)185 int zaxisCreate_(int zaxistype, int size, int id)
186 {
187   zaxis_t *zaxisptr = zaxisNewEntry(id);
188 
189   xassert(size >= 0);
190   zaxisptr->type = zaxistype;
191   zaxisptr->size = size;
192 
193   if ( zaxistype >= CDI_NumZaxistype || zaxistype < 0 )
194     Error("Internal problem! zaxistype=%d out of range (min=0/max=%d)!", zaxistype, CDI_NumZaxistype-1);
195 
196   const int zaxisID = zaxisptr->self;
197   cdiDefKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_NAME, ZaxistypeEntry[zaxistype].name);
198   if ( zaxistype != ZAXIS_GENERIC ) zaxisDefLongname(zaxisID, ZaxistypeEntry[zaxistype].longname);
199   cdiDefKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_UNITS, ZaxistypeEntry[zaxistype].units);
200 
201   const char *stdname = ZaxistypeEntry[zaxistype].stdname;
202   if ( *stdname )
203     cdiDefVarKeyBytes(&zaxisptr->keys, CDI_KEY_STDNAME, (const unsigned char*)stdname, (int)strlen(stdname)+1);
204 
205   zaxisptr->positive = ZaxistypeEntry[zaxistype].positive;
206 
207   return zaxisID;
208 }
209 
210 /*
211 @Function  zaxisCreate
212 @Title     Create a vertical Z-axis
213 
214 @Prototype int zaxisCreate(int zaxistype, int size)
215 @Parameter
216     @Item  zaxistype  The type of the Z-axis, one of the set of predefined CDI Z-axis types.
217                       The valid CDI Z-axis types are @func{ZAXIS_GENERIC}, @func{ZAXIS_SURFACE},
218                       @func{ZAXIS_HYBRID}, @func{ZAXIS_SIGMA}, @func{ZAXIS_PRESSURE}, @func{ZAXIS_HEIGHT},
219                       @func{ZAXIS_ISENTROPIC}, @func{ZAXIS_ALTITUDE}, @func{ZAXIS_MEANSEA}, @func{ZAXIS_TOA},
220                       @func{ZAXIS_SEA_BOTTOM}, @func{ZAXIS_ATMOSPHERE}, @func{ZAXIS_CLOUD_BASE},
221                       @func{ZAXIS_CLOUD_TOP}, @func{ZAXIS_ISOTHERM_ZERO}, @func{ZAXIS_SNOW},
222                       @func{ZAXIS_LAKE_BOTTOM}, @func{ZAXIS_SEDIMENT_BOTTOM}, @func{ZAXIS_SEDIMENT_BOTTOM_TA},
223                       @func{ZAXIS_SEDIMENT_BOTTOM_TW}, @func{ZAXIS_MIX_LAYER},
224                       @func{ZAXIS_DEPTH_BELOW_SEA} and @func{ZAXIS_DEPTH_BELOW_LAND}.
225     @Item  size       Number of levels.
226 
227 @Description
228 The function @func{zaxisCreate} creates a vertical Z-axis.
229 
230 @Result
231 @func{zaxisCreate} returns an identifier to the Z-axis.
232 
233 @Example
234 Here is an example using @func{zaxisCreate} to create a pressure level Z-axis:
235 
236 @Source
237 #include "cdi.h"
238    ...
239 #define  nlev    5
240    ...
241 double levs[nlev] = {101300, 92500, 85000, 50000, 20000};
242 int zaxisID;
243    ...
244 zaxisID = zaxisCreate(ZAXIS_PRESSURE, nlev);
245 zaxisDefLevels(zaxisID, levs);
246    ...
247 @EndSource
248 @EndFunction
249 */
zaxisCreate(int zaxistype,int size)250 int zaxisCreate(int zaxistype, int size)
251 {
252   if ( CDI_Debug ) Message("zaxistype: %d size: %d ", zaxistype, size);
253 
254   xassert(size);
255   zaxisInit();
256 
257   return zaxisCreate_(zaxistype, size, CDI_UNDEFID);
258 }
259 
260 static
zaxisDestroyKernel(zaxis_t * zaxisptr)261 void zaxisDestroyKernel( zaxis_t * zaxisptr )
262 {
263   xassert ( zaxisptr );
264 
265   const int id = zaxisptr->self;
266 
267   if ( zaxisptr->vals ) Free( zaxisptr->vals );
268 #ifndef USE_MPI
269   if ( zaxisptr->cvals )
270     {
271       for ( int i=0; i<zaxisptr->size; i++)
272         Free(zaxisptr->cvals[i]);
273       Free( zaxisptr->cvals );
274     }
275 #endif
276   if ( zaxisptr->lbounds ) Free( zaxisptr->lbounds );
277   if ( zaxisptr->ubounds ) Free( zaxisptr->ubounds );
278   if ( zaxisptr->weights ) Free( zaxisptr->weights );
279   if ( zaxisptr->vct )     Free( zaxisptr->vct );
280 
281   cdiDeleteKeys(id, CDI_GLOBAL);
282   cdiDeleteAtts(id, CDI_GLOBAL);
283 
284   Free(zaxisptr);
285 
286   reshRemove(id, &zaxisOps);
287 }
288 
289 /*
290 @Function  zaxisDestroy
291 @Title     Destroy a vertical Z-axis
292 
293 @Prototype void zaxisDestroy(int zaxisID)
294 @Parameter
295     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
296 
297 @EndFunction
298 */
zaxisDestroy(int zaxisID)299 void zaxisDestroy(int zaxisID)
300 {
301   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
302   zaxisDestroyKernel(zaxisptr);
303 }
304 
305 
306 static
zaxisDestroyP(void * zaxisptr)307 void zaxisDestroyP(void *zaxisptr)
308 {
309   zaxisDestroyKernel((zaxis_t *) zaxisptr);
310 }
311 
312 
zaxisNamePtr(int zaxistype)313 const char *zaxisNamePtr(int zaxistype)
314 {
315   const char *name = (zaxistype >= 0 && zaxistype < CDI_NumZaxistype)
316     ? ZaxistypeEntry[zaxistype].longname
317     : ZaxistypeEntry[ZAXIS_GENERIC].longname;
318   return name;
319 }
320 
321 
zaxisName(int zaxistype,char * zaxisname)322 void zaxisName(int zaxistype, char *zaxisname)
323 {
324   strcpy(zaxisname, zaxisNamePtr(zaxistype));
325 }
326 
327 /*
328 @Function  zaxisDefName
329 @Title     Define the name of a Z-axis
330 
331 @Prototype void zaxisDefName(int zaxisID, const char *name)
332 @Parameter
333     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
334     @Item  name     Name of the Z-axis.
335 
336 @Description
337 The function @func{zaxisDefName} defines the name of a Z-axis.
338 
339 @EndFunction
340 */
zaxisDefName(int zaxisID,const char * name)341 void zaxisDefName(int zaxisID, const char *name)
342 {
343   (void)cdiDefKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_NAME, name);
344 }
345 
346 /*
347 @Function  zaxisDefLongname
348 @Title     Define the longname of a Z-axis
349 
350 @Prototype void zaxisDefLongname(int zaxisID, const char *longname)
351 @Parameter
352     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
353     @Item  longname Longname of the Z-axis.
354 
355 @Description
356 The function @func{zaxisDefLongname} defines the longname of a Z-axis.
357 
358 @EndFunction
359 */
zaxisDefLongname(int zaxisID,const char * longname)360 void zaxisDefLongname(int zaxisID, const char *longname)
361 {
362   (void)cdiDefKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_LONGNAME, longname);
363 }
364 
365 /*
366 @Function  zaxisDefUnits
367 @Title     Define the units of a Z-axis
368 
369 @Prototype void zaxisDefUnits(int zaxisID, const char *units)
370 @Parameter
371     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
372     @Item  units    Units of the Z-axis.
373 
374 @Description
375 The function @func{zaxisDefUnits} defines the units of a Z-axis.
376 
377 @EndFunction
378 */
zaxisDefUnits(int zaxisID,const char * units)379 void zaxisDefUnits(int zaxisID, const char *units)
380 {
381   (void)cdiDefKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_UNITS, units);
382 }
383 
384 /*
385 @Function  zaxisInqName
386 @Title     Get the name of a Z-axis
387 
388 @Prototype void zaxisInqName(int zaxisID, char *name)
389 @Parameter
390     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
391     @Item  name     Name of the Z-axis. The caller must allocate space for the
392                     returned string. The maximum possible length, in characters, of
393                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
394 
395 @Description
396 The function @func{zaxisInqName} returns the name of a Z-axis.
397 
398 @Result
399 @func{zaxisInqName} returns the name of the Z-axis to the parameter name.
400 
401 @EndFunction
402 */
zaxisInqName(int zaxisID,char * name)403 void zaxisInqName(int zaxisID, char *name)
404 {
405   int length = CDI_MAX_NAME;
406   (void)cdiInqKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_NAME, name, &length);
407 }
408 
zaxisInqNamePtr(int zaxisID)409 const char *zaxisInqNamePtr(int zaxisID)
410 {
411   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
412   return cdiInqVarKeyString(&zaxisptr->keys, CDI_KEY_NAME);
413 }
414 
415 /*
416 @Function  zaxisInqLongname
417 @Title     Get the longname of a Z-axis
418 
419 @Prototype void zaxisInqLongname(int zaxisID, char *longname)
420 @Parameter
421     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
422     @Item  longname Longname of the Z-axis. The caller must allocate space for the
423                     returned string. The maximum possible length, in characters, of
424                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
425 
426 @Description
427 The function @func{zaxisInqLongname} returns the longname of a Z-axis.
428 
429 @Result
430 @func{zaxisInqLongname} returns the longname of the Z-axis to the parameter longname.
431 
432 @EndFunction
433 */
zaxisInqLongname(int zaxisID,char * longname)434 void zaxisInqLongname(int zaxisID, char *longname)
435 {
436   int length = CDI_MAX_NAME;
437   (void)cdiInqKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_LONGNAME, longname, &length);
438 }
439 
440 /*
441 @Function  zaxisInqUnits
442 @Title     Get the units of a Z-axis
443 
444 @Prototype void zaxisInqUnits(int zaxisID, char *units)
445 @Parameter
446     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
447     @Item  units    Units of the Z-axis. The caller must allocate space for the
448                     returned string. The maximum possible length, in characters, of
449                     the string is given by the predefined constant @func{CDI_MAX_NAME}.
450 
451 @Description
452 The function @func{zaxisInqUnits} returns the units of a Z-axis.
453 
454 @Result
455 @func{zaxisInqUnits} returns the units of the Z-axis to the parameter units.
456 
457 @EndFunction
458 */
zaxisInqUnits(int zaxisID,char * units)459 void zaxisInqUnits(int zaxisID, char *units)
460 {
461   int length = CDI_MAX_NAME;
462   (void)cdiInqKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_UNITS, units, &length);
463 }
464 
465 
zaxisInqStdname(int zaxisID,char * stdname)466 void zaxisInqStdname(int zaxisID, char *stdname)
467 {
468   int length = CDI_MAX_NAME;
469   (void)cdiInqKeyString(zaxisID, CDI_GLOBAL, CDI_KEY_STDNAME, stdname, &length);
470 }
471 
472 
zaxisDefDatatype(int zaxisID,int datatype)473 void zaxisDefDatatype(int zaxisID, int datatype)
474 {
475   cdiDefKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_DATATYPE, datatype);
476 }
477 
478 
zaxisInqDatatype(int zaxisID)479 int zaxisInqDatatype(int zaxisID)
480 {
481   int datatype = 0;
482   cdiInqKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_DATATYPE, &datatype);
483   return datatype;
484 }
485 
486 
zaxisDefPositive(int zaxisID,int positive)487 void zaxisDefPositive(int zaxisID, int positive)
488 {
489   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
490 
491   if ( zaxisptr->positive != (unsigned)positive )
492     {
493       zaxisptr->positive = (unsigned)positive;
494       reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
495     }
496 }
497 
498 
zaxisInqPositive(int zaxisID)499 int zaxisInqPositive(int zaxisID)
500 {
501   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
502   return (int)zaxisptr->positive;
503 }
504 
505 
zaxisDefScalar(int zaxisID)506 void zaxisDefScalar(int zaxisID)
507 {
508   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
509 
510   zaxisptr->scalar = 1;
511   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
512 }
513 
zaxisInqScalar(int zaxisID)514 int zaxisInqScalar(int zaxisID)
515 {
516   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
517   return zaxisptr->scalar;
518 }
519 
520 /*
521 @Function  zaxisDefLevels
522 @Title     Define the levels of a Z-axis
523 
524 @Prototype void zaxisDefLevels(int zaxisID, const double *levels)
525 @Parameter
526     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
527     @Item  levels   All levels of the Z-axis.
528 
529 @Description
530 The function @func{zaxisDefLevels} defines the levels of a Z-axis.
531 
532 @EndFunction
533 */
zaxisDefLevels(int zaxisID,const double * levels)534 void zaxisDefLevels(int zaxisID, const double *levels)
535 {
536   if ( levels )
537     {
538       zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
539       const size_t size = (size_t)zaxisptr->size;
540       xassert(size);
541 
542       if (zaxisptr->vals == NULL && size)
543         zaxisptr->vals = (double*) Malloc(size*sizeof(double));
544 
545       double *vals = zaxisptr->vals;
546 
547       for ( size_t ilev = 0; ilev < size; ++ilev )
548         vals[ilev] = levels[ilev];
549 
550       reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
551     }
552 }
553 
554 
zaxisDefCvals(int zaxisID,const char ** cvals,int clen)555 void zaxisDefCvals(int zaxisID, const char **cvals, int clen)
556 {
557 #ifndef USE_MPI
558   if ( cvals && clen )
559     {
560       zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
561       const size_t size = zaxisptr->size;
562       xassert(size);
563 
564       zaxisptr->clength = clen;
565       if (size) zaxisptr->cvals = (char**) Malloc(size*sizeof(char *));
566 
567       for ( size_t ilev = 0; ilev < size; ++ilev )
568         {
569           zaxisptr->cvals[ilev] = (char*) Malloc(clen*sizeof(char));
570           memcpy(zaxisptr->cvals[ilev], cvals[ilev], clen*sizeof(char));
571         }
572       reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
573     }
574 #else
575   Error("This function was disabled!");
576 #endif
577 }
578 
579 /*
580 @Function  zaxisDefLevel
581 @Title     Define one level of a Z-axis
582 
583 @Prototype void zaxisDefLevel(int zaxisID, int levelID, double level)
584 @Parameter
585     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate}.
586     @Item  levelID  Level identifier.
587     @Item  level    Level.
588 
589 @Description
590 The function @func{zaxisDefLevel} defines one level of a Z-axis.
591 
592 @EndFunction
593 */
zaxisDefLevel(int zaxisID,int levelID,double level)594 void zaxisDefLevel(int zaxisID, int levelID, double level)
595 {
596   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
597   const int size = zaxisptr->size;
598   xassert(size);
599   xassert(levelID >= 0 && levelID < size);
600 
601   if (zaxisptr->vals == NULL && size)
602     zaxisptr->vals = (double*) Malloc((size_t)size*sizeof(double));
603 
604   if ( levelID >= 0 && levelID < size )
605     zaxisptr->vals[levelID] = level;
606 
607   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
608 }
609 
610 
zaxisDefNlevRef(int zaxisID,int nlev)611 void zaxisDefNlevRef(int zaxisID, int nlev)
612 {
613   cdiDefKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_NLEV, nlev);
614 }
615 
616 
zaxisInqNlevRef(int zaxisID)617 int zaxisInqNlevRef(int zaxisID)
618 {
619   int nlev = 0;
620   cdiInqKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_NLEV, &nlev);
621   return nlev;
622 }
623 
624 /*
625 @Function  zaxisDefNumber
626 @Title     Define the reference number for a generalized Z-axis
627 
628 @Prototype void zaxisDefNumber(int zaxisID, int number)
629 @Parameter
630     @Item  zaxisID     Z-axis ID, from a previous call to @fref{zaxisCreate}.
631     @Item  number      Reference number for a generalized Z-axis.
632 
633 @Description
634 The function @func{zaxisDefNumber} defines the reference number for a generalized Z-axis.
635 
636 @EndFunction
637 */
zaxisDefNumber(int zaxisID,int number)638 void zaxisDefNumber(int zaxisID, int number)
639 {
640   cdiDefKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_NUMBEROFVGRIDUSED, number);
641 }
642 
643 /*
644 @Function  zaxisInqNumber
645 @Title     Get the reference number to a generalized Z-axis
646 
647 @Prototype int zaxisInqNumber(int zaxisID)
648 @Parameter
649     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
650 
651 @Description
652 The function @func{zaxisInqNumber} returns the reference number to a generalized Z-axis.
653 
654 @Result
655 @func{zaxisInqNumber} returns the reference number to a generalized Z-axis.
656 @EndFunction
657 */
zaxisInqNumber(int zaxisID)658 int zaxisInqNumber(int zaxisID)
659 {
660   int referenceNumber = 0;
661   cdiInqKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_NUMBEROFVGRIDUSED, &referenceNumber);
662   return referenceNumber;
663 }
664 
665 /*
666 @Function  zaxisDefUUID
667 @Title     Define the UUID for a genralized Z-axis
668 
669 @Prototype void zaxisDefUUID(int zaxisID, const char *uuid)
670 @Parameter
671     @Item  zaxisID     Z-axis ID, from a previous call to @fref{zaxisCreate}.
672     @Item  uuid        UUID for a generalized Z-axis.
673 
674 @Description
675 The function @func{zaxisDefUUID} defines the UUID for a generalized  Z-axis.
676 
677 @EndFunction
678 */
zaxisDefUUID(int zaxisID,const unsigned char uuid[CDI_UUID_SIZE])679 void zaxisDefUUID(int zaxisID, const unsigned char uuid[CDI_UUID_SIZE])
680 {
681   cdiDefKeyBytes(zaxisID, CDI_GLOBAL, CDI_KEY_UUID, uuid, CDI_UUID_SIZE);
682 
683   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
684 }
685 
686 /*
687 @Function  zaxisInqUUID
688 @Title     Get the uuid to a generalized Z-axis
689 
690 @Prototype void zaxisInqUUID(int zaxisID, char *uuid)
691 @Parameter
692     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
693     @Item uuid A user supplied buffer of at least 16 bytes.
694 
695 @Description
696 The function @func{zaxisInqUUID} returns the UUID to a generalized Z-axis.
697 
698 @Result
699 @func{zaxisInqUUID} returns the UUID to a generalized Z-axis to the parameter uuid.
700 @EndFunction
701 */
zaxisInqUUID(int zaxisID,unsigned char uuid[CDI_UUID_SIZE])702 void zaxisInqUUID(int zaxisID, unsigned char uuid[CDI_UUID_SIZE])
703 {
704   memset(uuid, 0, CDI_UUID_SIZE);
705   int length = CDI_UUID_SIZE;
706   cdiInqKeyBytes(zaxisID, CDI_GLOBAL, CDI_KEY_UUID, uuid, &length);
707 }
708 
709 /*
710 @Function  zaxisInqLevel
711 @Title     Get one level of a Z-axis
712 
713 @Prototype double zaxisInqLevel(int zaxisID, int levelID)
714 @Parameter
715     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
716     @Item  levelID  Level index (range: 0 to nlevel-1).
717 
718 @Description
719 The function @func{zaxisInqLevel} returns one level of a Z-axis.
720 
721 @Result
722 @func{zaxisInqLevel} returns the level of a Z-axis.
723 @EndFunction
724 */
zaxisInqLevel(int zaxisID,int levelID)725 double zaxisInqLevel(int zaxisID, int levelID)
726 {
727   double level = 0;
728   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
729   if ( zaxisptr->vals && levelID >= 0 && levelID < zaxisptr->size )
730     level = zaxisptr->vals[levelID];
731 
732   return level;
733 }
734 
735 
zaxisInqLbound(int zaxisID,int levelID)736 double zaxisInqLbound(int zaxisID, int levelID)
737 {
738   double level = 0;
739   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
740   if ( zaxisptr->lbounds && levelID >= 0 && levelID < zaxisptr->size )
741     level = zaxisptr->lbounds[levelID];
742 
743   return level;
744 }
745 
746 
zaxisInqUbound(int zaxisID,int levelID)747 double zaxisInqUbound(int zaxisID, int levelID)
748 {
749   double level = 0;
750   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
751   if ( zaxisptr->ubounds && levelID >= 0 && levelID < zaxisptr->size )
752     level = zaxisptr->ubounds[levelID];
753 
754   return level;
755 }
756 
757 
zaxisInqLevelsPtr(int zaxisID)758 const double *zaxisInqLevelsPtr(int zaxisID)
759 {
760   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
761   return zaxisptr->vals;
762 }
763 
764 
765 #ifndef USE_MPI
zaxisInqCValsPtr(int zaxisID)766 char **zaxisInqCValsPtr(int zaxisID)
767 {
768   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
769   return zaxisptr->cvals;
770 }
771 #endif
772 
773 /*
774 @Function  zaxisInqLevels
775 @Title     Get all levels of a Z-axis
776 
777 @Prototype void zaxisInqLevels(int zaxisID, double *levels)
778 @Parameter
779     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
780     @Item  levels   Pointer to the location into which the levels are read.
781                     The caller must allocate space for the returned values.
782 
783 @Description
784 The function @func{zaxisInqLevels} returns all levels of a Z-axis.
785 
786 @Result
787 @func{zaxisInqLevels} saves all levels to the parameter @func{levels}.
788 @EndFunction
789 */
zaxisInqLevels(int zaxisID,double * levels)790 int zaxisInqLevels(int zaxisID, double *levels)
791 {
792   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
793 
794   int size = 0;
795   if ( zaxisptr->vals )
796     {
797       size = zaxisptr->size;
798 
799       if ( levels )
800         for ( int i = 0; i < size; i++ )
801           levels[i] = zaxisptr->vals[i];
802     }
803 
804   return size;
805 }
806 
807 
zaxisInqCLen(int zaxisID)808 int zaxisInqCLen(int zaxisID)
809 {
810   int clen = 0;
811 #ifndef USE_MPI
812   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
813   if ( zaxisptr->cvals && zaxisptr->clength)
814     clen = zaxisptr->clength;
815 #endif
816 
817   return clen;
818 }
819 
820 
zaxisInqCVals(int zaxisID,char *** clevels)821 int zaxisInqCVals(int zaxisID, char ***clevels)
822 {
823   int size = 0;
824 #ifndef USE_MPI
825   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
826   if ( zaxisptr->cvals )
827     {
828       size = zaxisptr->size;
829       const size_t clen = zaxisptr->clength;
830       if ( size && clen )
831         {
832           (*clevels) = (char**) Malloc(size*sizeof(char*));
833           for ( int i = 0; i < size; i++ )
834             {
835               (*clevels)[i] = (char*) Malloc(clen*sizeof(char));
836               memcpy((*clevels)[i], zaxisptr->cvals[i], clen*sizeof(char));
837             }
838           }
839     }
840 #endif
841 
842   return size;
843 }
844 
845 
zaxisInqLbounds(int zaxisID,double * lbounds)846 int zaxisInqLbounds(int zaxisID, double *lbounds)
847 {
848   int size = 0;
849   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
850   if ( zaxisptr->lbounds )
851     {
852       size = zaxisptr->size;
853 
854       if ( lbounds )
855         for ( int i = 0; i < size; i++ )
856           lbounds[i] = zaxisptr->lbounds[i];
857     }
858 
859   return size;
860 }
861 
862 
zaxisInqUbounds(int zaxisID,double * ubounds)863 int zaxisInqUbounds(int zaxisID, double *ubounds)
864 {
865   int size = 0;
866   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
867   if ( zaxisptr->ubounds )
868     {
869       size = zaxisptr->size;
870 
871       if ( ubounds )
872         for ( int i = 0; i < size; i++ )
873           ubounds[i] = zaxisptr->ubounds[i];
874     }
875 
876   return size;
877 }
878 
879 
zaxisInqWeights(int zaxisID,double * weights)880 int zaxisInqWeights(int zaxisID, double *weights)
881 {
882   int size = 0;
883   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
884   if ( zaxisptr->weights )
885     {
886       size = zaxisptr->size;
887 
888       if ( weights )
889         for ( int i = 0; i < size; i++ )
890           weights[i] = zaxisptr->weights[i];
891     }
892 
893   return size;
894 }
895 
896 
zaxisInqLevelID(int zaxisID,double level)897 int zaxisInqLevelID(int zaxisID, double level)
898 {
899   int levelID = CDI_UNDEFID;
900   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
901   if ( zaxisptr->vals )
902     {
903       const int size = zaxisptr->size;
904       for ( int i = 0; i < size; i++ )
905         if ( fabs(level-zaxisptr->vals[i]) < DBL_EPSILON )
906           {
907             levelID = i;
908             break;
909           }
910     }
911 
912   return levelID;
913 }
914 
915 /*
916 @Function  zaxisInqType
917 @Title     Get the type of a Z-axis
918 
919 @Prototype int zaxisInqType(int zaxisID)
920 @Parameter
921     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
922 
923 @Description
924 The function @func{zaxisInqType} returns the type of a Z-axis.
925 
926 @Result
927 @func{zaxisInqType} returns the type of the Z-axis,
928 one of the set of predefined CDI Z-axis types.
929 The valid CDI Z-axis types are @func{ZAXIS_GENERIC}, @func{ZAXIS_SURFACE},
930 @func{ZAXIS_HYBRID}, @func{ZAXIS_SIGMA}, @func{ZAXIS_PRESSURE}, @func{ZAXIS_HEIGHT},
931 @func{ZAXIS_ISENTROPIC}, @func{ZAXIS_ALTITUDE}, @func{ZAXIS_MEANSEA}, @func{ZAXIS_TOA},
932 @func{ZAXIS_SEA_BOTTOM}, @func{ZAXIS_ATMOSPHERE}, @func{ZAXIS_CLOUD_BASE},
933 @func{ZAXIS_CLOUD_TOP}, @func{ZAXIS_ISOTHERM_ZERO}, @func{ZAXIS_SNOW},
934 @func{ZAXIS_LAKE_BOTTOM}, @func{ZAXIS_SEDIMENT_BOTTOM}, @func{ZAXIS_SEDIMENT_BOTTOM_TA},
935 @func{ZAXIS_SEDIMENT_BOTTOM_TW}, @func{ZAXIS_MIX_LAYER},
936 @func{ZAXIS_DEPTH_BELOW_SEA} and @func{ZAXIS_DEPTH_BELOW_LAND}.
937 
938 @EndFunction
939 */
zaxisInqType(int zaxisID)940 int zaxisInqType(int zaxisID)
941 {
942   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
943   return zaxisptr->type;
944 }
945 
946 /*
947 @Function  zaxisInqSize
948 @Title     Get the size of a Z-axis
949 
950 @Prototype int zaxisInqSize(int zaxisID)
951 @Parameter
952     @Item  zaxisID  Z-axis ID, from a previous call to @fref{zaxisCreate} or @fref{vlistInqVarZaxis}.
953 
954 @Description
955 The function @func{zaxisInqSize} returns the size of a Z-axis.
956 
957 @Result
958 @func{zaxisInqSize} returns the number of levels of a Z-axis.
959 
960 @EndFunction
961 */
zaxisInqSize(int zaxisID)962 int zaxisInqSize(int zaxisID)
963 {
964   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
965   return zaxisptr->size;
966 }
967 
968 
cdiCheckZaxis(int zaxisID)969 void cdiCheckZaxis(int zaxisID)
970 {
971   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
972 
973   if ( zaxisInqType(zaxisID) == ZAXIS_GENERIC && zaxisptr->vals )
974     {
975       const int size = zaxisptr->size;
976       if ( size > 1 )
977         {
978           /* check direction */
979           if ( ! zaxisptr->direction )
980             {
981               int ups = 0, downs = 0;
982               for ( int i = 1; i < size; i++ )
983                 {
984                   ups += (zaxisptr->vals[i] > zaxisptr->vals[i-1]);
985                   downs += (zaxisptr->vals[i] < zaxisptr->vals[i-1]);
986                 }
987               if ( ups == size-1 )
988                 {
989                   zaxisptr->direction = LevelUp;
990                 }
991               else if ( downs == size-1 )
992                 {
993                   zaxisptr->direction = LevelDown;
994                 }
995               else /* !zaxisptr->direction */
996                 {
997                   Warning("Direction undefined for zaxisID %d", zaxisID);
998                 }
999             }
1000         }
1001     }
1002 }
1003 
1004 
zaxisDefVct(int zaxisID,int size,const double * vct)1005 void zaxisDefVct(int zaxisID, int size, const double *vct)
1006 {
1007   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1008 
1009   if ( zaxisptr->vct == 0 || zaxisptr->vctsize != size )
1010     {
1011       zaxisptr->vctsize = size;
1012       zaxisptr->vct = (double *) Realloc(zaxisptr->vct, (size_t)size*sizeof(double));
1013     }
1014 
1015   if (vct) memcpy(zaxisptr->vct, vct, (size_t)size*sizeof(double));
1016   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
1017 }
1018 
1019 
zaxisInqVct(int zaxisID,double * vct)1020 void zaxisInqVct(int zaxisID, double *vct)
1021 {
1022   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1023   memcpy(vct, zaxisptr->vct, (size_t)zaxisptr->vctsize * sizeof (double));
1024 }
1025 
1026 
zaxisInqVctSize(int zaxisID)1027 int zaxisInqVctSize(int zaxisID)
1028 {
1029   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1030   return zaxisptr->vctsize;
1031 }
1032 
1033 
zaxisInqVctPtr(int zaxisID)1034 const double *zaxisInqVctPtr(int zaxisID)
1035 {
1036   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1037   return zaxisptr->vct;
1038 }
1039 
1040 
zaxisDefLbounds(int zaxisID,const double * lbounds)1041 void zaxisDefLbounds(int zaxisID, const double *lbounds)
1042 {
1043   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1044 
1045   const size_t size = (size_t)zaxisptr->size;
1046 
1047   if ( CDI_Debug )
1048     if ( zaxisptr->lbounds )
1049       Warning("Lower bounds already defined for zaxisID = %d", zaxisID);
1050 
1051   if ( zaxisptr->lbounds == NULL )
1052     zaxisptr->lbounds = (double *) Malloc(size*sizeof(double));
1053 
1054   if (lbounds) memcpy(zaxisptr->lbounds, lbounds, size*sizeof(double));
1055   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
1056 }
1057 
1058 
zaxisDefUbounds(int zaxisID,const double * ubounds)1059 void zaxisDefUbounds(int zaxisID, const double *ubounds)
1060 {
1061   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1062 
1063   const size_t size = (size_t)zaxisptr->size;
1064 
1065   if ( CDI_Debug )
1066     if ( zaxisptr->ubounds )
1067       Warning("Upper bounds already defined for zaxisID = %d", zaxisID);
1068 
1069   if ( zaxisptr->ubounds == NULL )
1070     zaxisptr->ubounds = (double *) Malloc(size*sizeof(double));
1071 
1072   if (ubounds) memcpy(zaxisptr->ubounds, ubounds, size*sizeof(double));
1073   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
1074 }
1075 
1076 
zaxisDefWeights(int zaxisID,const double * weights)1077 void zaxisDefWeights(int zaxisID, const double *weights)
1078 {
1079   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1080 
1081   const size_t size = (size_t)zaxisptr->size;
1082 
1083   if ( CDI_Debug )
1084     if ( zaxisptr->weights != NULL )
1085       Warning("Weights already defined for zaxisID = %d", zaxisID);
1086 
1087   if ( zaxisptr->weights == NULL )
1088     zaxisptr->weights = (double *) Malloc(size*sizeof(double));
1089 
1090   memcpy(zaxisptr->weights, weights, size*sizeof(double));
1091   reshSetStatus(zaxisID, &zaxisOps, RESH_DESYNC_IN_USE);
1092 }
1093 
1094 
zaxisChangeType(int zaxisID,int zaxistype)1095 void zaxisChangeType(int zaxisID, int zaxistype)
1096 {
1097   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1098   zaxisptr->type = zaxistype;
1099 }
1100 
1101 
zaxisResize(int zaxisID,int size)1102 void zaxisResize(int zaxisID, int size)
1103 {
1104   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1105 
1106   xassert(size >= 0);
1107 
1108   zaxisptr->size = size;
1109 
1110   if ( zaxisptr->vals )
1111     zaxisptr->vals = (double *) Realloc(zaxisptr->vals, (size_t)size*sizeof(double));
1112 }
1113 
1114 static inline
zaxisCopyKeyStr(zaxis_t * zaxisptr1,zaxis_t * zaxisptr2,int key)1115 void zaxisCopyKeyStr(zaxis_t *zaxisptr1, zaxis_t *zaxisptr2, int key)
1116 {
1117   cdi_key_t *keyp = find_key(&zaxisptr1->keys, key);
1118   if (keyp && keyp->type == KEY_BYTES)
1119     cdiDefVarKeyBytes(&zaxisptr2->keys, key, (const unsigned char*)keyp->v.s, (int)keyp->length);
1120 }
1121 
1122 
zaxisDuplicate(int zaxisID)1123 int zaxisDuplicate(int zaxisID)
1124 {
1125   zaxis_t *zaxisptr = zaxis_to_pointer(zaxisID);
1126 
1127   const int zaxistype = zaxisInqType(zaxisID);
1128   const int zaxissize = zaxisInqSize(zaxisID);
1129 
1130   const int zaxisIDnew = zaxisCreate(zaxistype, zaxissize);
1131   zaxis_t *zaxisptrnew = zaxis_to_pointer(zaxisIDnew);
1132 
1133   zaxis_copy(zaxisptrnew, zaxisptr);
1134 
1135   zaxisCopyKeyStr(zaxisptr, zaxisptrnew, CDI_KEY_NAME);
1136   zaxisCopyKeyStr(zaxisptr, zaxisptrnew, CDI_KEY_LONGNAME);
1137   zaxisCopyKeyStr(zaxisptr, zaxisptrnew, CDI_KEY_UNITS);
1138 
1139   if ( zaxisptr->vals )
1140     {
1141       const size_t size = (size_t)zaxissize;
1142       zaxisptrnew->vals = (double *) Malloc(size * sizeof (double));
1143       memcpy(zaxisptrnew->vals, zaxisptr->vals, size * sizeof (double));
1144     }
1145 
1146   if ( zaxisptr->lbounds )
1147     {
1148       const size_t size = (size_t)zaxissize;
1149       zaxisptrnew->lbounds = (double *) Malloc(size * sizeof (double));
1150       memcpy(zaxisptrnew->lbounds, zaxisptr->lbounds, size * sizeof(double));
1151     }
1152 
1153   if ( zaxisptr->ubounds )
1154     {
1155       const size_t size = (size_t)zaxissize;
1156       zaxisptrnew->ubounds = (double *) Malloc(size * sizeof (double));
1157       memcpy(zaxisptrnew->ubounds, zaxisptr->ubounds, size * sizeof (double));
1158     }
1159 
1160   if ( zaxisptr->vct )
1161     {
1162       const size_t size = (size_t)zaxisptr->vctsize;
1163       if ( size )
1164         {
1165           zaxisptrnew->vctsize = (int)size;
1166           zaxisptrnew->vct = (double *) Malloc(size * sizeof (double));
1167           memcpy(zaxisptrnew->vct, zaxisptr->vct, size * sizeof (double));
1168         }
1169     }
1170 
1171   zaxisptrnew->atts.nelems = 0;
1172   cdiCopyAtts(zaxisID, CDI_GLOBAL, zaxisIDnew, CDI_GLOBAL);
1173 
1174   return zaxisIDnew;
1175 }
1176 
1177 static
zaxisPrintKernel(zaxis_t * zaxisptr,FILE * fp)1178 void zaxisPrintKernel(zaxis_t *zaxisptr, FILE *fp)
1179 {
1180   xassert(zaxisptr);
1181 
1182   int zaxisID = zaxisptr->self;
1183   int datatype = CDI_UNDEFID;
1184   cdiInqKeyInt(zaxisID, CDI_GLOBAL, CDI_KEY_DATATYPE, &datatype);
1185 
1186   const int type    = zaxisptr->type;
1187   const int nlevels = zaxisptr->size;
1188 
1189   const int dig = (datatype == CDI_DATATYPE_FLT64) ? 15 : 7;
1190 
1191   fprintf(fp, "zaxistype = %s\n", zaxisNamePtr(type));
1192   fprintf(fp, "size      = %d\n", nlevels);
1193   if ( nlevels == 1 )
1194     {
1195       const bool zscalar = (bool)zaxisptr->scalar;
1196       if ( zscalar ) fprintf(fp, "scalar    = true\n");
1197     }
1198 
1199   const char *string = cdiInqVarKeyString(&zaxisptr->keys, CDI_KEY_NAME);
1200   if ( string[0] ) fprintf(fp, "name      = %s\n", string);
1201   string = cdiInqVarKeyString(&zaxisptr->keys, CDI_KEY_LONGNAME);
1202   if ( string[0] ) fprintf(fp, "longname  = %s\n", string);
1203   string = cdiInqVarKeyString(&zaxisptr->keys, CDI_KEY_UNITS);
1204   if ( string[0] ) fprintf(fp, "units     = %s\n", string);
1205 
1206   if ( zaxisptr->vals )
1207     {
1208       int nbyte0 = fprintf(fp, "levels    = ");
1209       int nbyte = nbyte0;
1210       for ( int levelID = 0; levelID < nlevels; levelID++ )
1211         {
1212           if ( nbyte > 80 )
1213             {
1214               fprintf(fp, "\n");
1215               fprintf(fp, "%*s", nbyte0, "");
1216               nbyte = nbyte0;
1217             }
1218           nbyte += fprintf(fp, "%.*g ", dig, zaxisptr->vals[levelID]);
1219         }
1220       fprintf(fp, "\n");
1221     }
1222 
1223   if ( zaxisptr->lbounds && zaxisptr->ubounds )
1224     {
1225       int nbyte0 = fprintf(fp, "lbounds   = ");
1226       int nbyte = nbyte0;
1227       for ( int levelID = 0; levelID < nlevels; levelID++ )
1228 	{
1229 	  if ( nbyte > 80 )
1230 	    {
1231 	      fprintf(fp, "\n");
1232 	      fprintf(fp, "%*s", nbyte0, "");
1233 	      nbyte = nbyte0;
1234 	    }
1235 	  nbyte += fprintf(fp, "%.*g ", dig, zaxisptr->lbounds[levelID]);
1236 	}
1237       fprintf(fp, "\n");
1238 
1239       nbyte0 = fprintf(fp, "ubounds   = ");
1240       nbyte = nbyte0;
1241       for ( int levelID = 0; levelID < nlevels; levelID++ )
1242 	{
1243 	  if ( nbyte > 80 )
1244 	    {
1245 	      fprintf(fp, "\n");
1246 	      fprintf(fp, "%*s", nbyte0, "");
1247 	      nbyte = nbyte0;
1248 	    }
1249 	  nbyte += fprintf(fp, "%.*g ", dig, zaxisptr->ubounds[levelID]);
1250 	}
1251       fprintf(fp, "\n");
1252     }
1253 
1254   if ( type == ZAXIS_HYBRID || type == ZAXIS_HYBRID_HALF )
1255     {
1256       const int vctsize = zaxisptr->vctsize;
1257       const double *vct = zaxisptr->vct;
1258       fprintf(fp, "vctsize   = %d\n", vctsize);
1259       if ( vctsize )
1260         {
1261           int nbyte0 = fprintf(fp, "vct       = ");
1262           int nbyte = nbyte0;
1263           for ( int i = 0; i < vctsize; i++ )
1264             {
1265               if ( nbyte > 70 || i == vctsize/2 )
1266                 {
1267                   fprintf(fp, "\n%*s", nbyte0, "");
1268                   nbyte = nbyte0;
1269                 }
1270               nbyte += fprintf(fp, "%.15g ", vct[i]);
1271             }
1272           fprintf(fp, "\n");
1273         }
1274     }
1275 }
1276 
1277 
1278 static
zaxisPrintP(void * voidptr,FILE * fp)1279 void zaxisPrintP(void *voidptr, FILE *fp)
1280 {
1281   zaxis_t *zaxisptr = (zaxis_t *) voidptr;
1282 
1283   xassert(zaxisptr);
1284 
1285   zaxisPrintKernel(zaxisptr, fp);
1286 }
1287 
1288 
1289 static
zaxisCompareP(zaxis_t * z1,zaxis_t * z2)1290 int zaxisCompareP(zaxis_t *z1, zaxis_t *z2)
1291 {
1292   enum { differ = 1 };
1293   int diff = 0;
1294   xassert(z1 && z2);
1295 
1296   diff |= (z1->type != z2->type)
1297     | (cdiInqVarKeyInt(&z1->keys, CDI_KEY_TYPEOFFIRSTFIXEDSURFACE) != cdiInqVarKeyInt(&z2->keys, CDI_KEY_TYPEOFFIRSTFIXEDSURFACE))
1298     | (cdiInqVarKeyInt(&z1->keys, CDI_KEY_DATATYPE) != cdiInqVarKeyInt(&z2->keys, CDI_KEY_DATATYPE))
1299     | (z1->direction != z2->direction)
1300     | (z1->size != z2->size)
1301     | (z1->vctsize != z2->vctsize)
1302     | (z1->positive != z2->positive);
1303 
1304   if ( diff ) return differ;
1305 
1306   int size = z1->size;
1307   int anyPresent = 0;
1308   int present = (z1->vals != NULL);
1309   diff |= (present ^ (z2->vals != NULL));
1310   anyPresent |= present;
1311   if (!diff && present)
1312     {
1313       const double *p = z1->vals, *q = z2->vals;
1314       for ( int i = 0; i < size; i++ )
1315         diff |= IS_NOT_EQUAL(p[i], q[i]);
1316     }
1317 
1318   present = (z1->lbounds != NULL);
1319   diff |= (present ^ (z2->lbounds != NULL));
1320   anyPresent |= present;
1321   if (!diff && present)
1322     {
1323       const double *p = z1->lbounds, *q = z2->lbounds;
1324       for ( int i = 0; i < size; i++ )
1325         diff |= IS_NOT_EQUAL(p[i], q[i]);
1326     }
1327 
1328   present = (z1->ubounds != NULL);
1329   diff |= (present ^ (z2->ubounds != NULL));
1330   anyPresent |= present;
1331   if (!diff && present)
1332     {
1333       const double *p = z1->ubounds, *q = z2->ubounds;
1334       for ( int i = 0; i < size; ++i )
1335         diff |= IS_NOT_EQUAL(p[i], q[i]);
1336     }
1337 
1338   present = (z1->weights != NULL);
1339   diff |= (present ^ (z2->weights != NULL));
1340   anyPresent |= present;
1341   if (!diff && present)
1342     {
1343       const double *p = z1->weights, *q = z2->weights;
1344       for ( int i = 0; i < size; ++i )
1345         diff |= IS_NOT_EQUAL(p[i], q[i]);
1346     }
1347 
1348   present = (z1->vct != NULL);
1349   diff |= (present ^ (z2->vct != NULL));
1350   if (!diff && present)
1351     {
1352       int vctsize = z1->vctsize;
1353       xassert(vctsize);
1354       const double *p = z1->vct, *q = z2->vct;
1355       for ( int i = 0; i < vctsize; ++i )
1356         diff |= IS_NOT_EQUAL(p[i], q[i]);
1357     }
1358 
1359   if (anyPresent)
1360     xassert(size);
1361 
1362   diff |= strcmp(cdiInqVarKeyString(&z1->keys, CDI_KEY_NAME), cdiInqVarKeyString(&z2->keys, CDI_KEY_NAME))
1363     | strcmp(cdiInqVarKeyString(&z1->keys, CDI_KEY_LONGNAME), cdiInqVarKeyString(&z2->keys, CDI_KEY_LONGNAME))
1364     | strcmp(cdiInqVarKeyString(&z1->keys, CDI_KEY_STDNAME), cdiInqVarKeyString(&z2->keys, CDI_KEY_STDNAME))
1365     | strcmp(cdiInqVarKeyString(&z1->keys, CDI_KEY_UNITS), cdiInqVarKeyString(&z2->keys, CDI_KEY_UNITS));
1366 
1367   return diff != 0;
1368 }
1369 
1370 
1371 static
zaxisTxCode(void)1372 int zaxisTxCode(void)
1373 {
1374   return ZAXIS;
1375 }
1376 
1377 enum { zaxisNint     = 6,
1378        vals     = 1 << 0,
1379        lbounds  = 1 << 1,
1380        ubounds  = 1 << 2,
1381        weights  = 1 << 3,
1382        vct      = 1 << 4,
1383 };
1384 
1385 static
zaxisGetMemberMask(zaxis_t * zaxisP)1386 int zaxisGetMemberMask( zaxis_t * zaxisP )
1387 {
1388   int memberMask = 0;
1389 
1390   if ( zaxisP->vals )      memberMask |= vals;
1391   if ( zaxisP->lbounds )   memberMask |= lbounds;
1392   if ( zaxisP->ubounds )   memberMask |= ubounds;
1393   if ( zaxisP->weights )   memberMask |= weights;
1394   if ( zaxisP->vct )       memberMask |= vct;
1395 
1396   return memberMask;
1397 }
1398 
1399 static int
zaxisGetPackSize(void * voidP,void * context)1400 zaxisGetPackSize(void * voidP, void *context)
1401 {
1402   zaxis_t * zaxisP = ( zaxis_t * ) voidP;
1403   int packBufferSize = serializeGetSize(zaxisNint, CDI_DATATYPE_INT, context)
1404     + serializeGetSize(1, CDI_DATATYPE_UINT32, context);
1405 
1406   if (zaxisP->vals || zaxisP->lbounds || zaxisP->ubounds || zaxisP->weights)
1407     xassert(zaxisP->size);
1408 
1409   if ( zaxisP->vals )
1410     packBufferSize += serializeGetSize(zaxisP->size, CDI_DATATYPE_FLT64, context)
1411       + serializeGetSize(1, CDI_DATATYPE_UINT32, context);
1412 
1413   if ( zaxisP->lbounds )
1414     packBufferSize += serializeGetSize(zaxisP->size, CDI_DATATYPE_FLT64, context)
1415       + serializeGetSize(1, CDI_DATATYPE_UINT32, context);
1416 
1417   if ( zaxisP->ubounds )
1418     packBufferSize += serializeGetSize(zaxisP->size, CDI_DATATYPE_FLT64, context)
1419       + serializeGetSize(1, CDI_DATATYPE_UINT32, context);
1420 
1421   if ( zaxisP->weights )
1422     packBufferSize += serializeGetSize(zaxisP->size, CDI_DATATYPE_FLT64, context)
1423       + serializeGetSize(1, CDI_DATATYPE_UINT32, context);
1424 
1425   if ( zaxisP->vct )
1426     {
1427       xassert ( zaxisP->vctsize );
1428       packBufferSize += serializeGetSize(zaxisP->vctsize, CDI_DATATYPE_FLT64, context)
1429         + serializeGetSize(1, CDI_DATATYPE_UINT32, context);
1430     }
1431 
1432   packBufferSize += serializeKeysGetPackSize(&zaxisP->keys, context);
1433 
1434   packBufferSize += serializeGetSize(1, CDI_DATATYPE_UCHAR, context);
1435 
1436   return packBufferSize;
1437 }
1438 
1439 
1440 void
zaxisUnpack(char * unpackBuffer,int unpackBufferSize,int * unpackBufferPos,int originNamespace,void * context,int force_id)1441 zaxisUnpack(char * unpackBuffer, int unpackBufferSize,
1442             int * unpackBufferPos, int originNamespace, void *context,
1443             int force_id)
1444 {
1445   int intBuffer[zaxisNint], memberMask;
1446   uint32_t d;
1447 
1448   serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1449                   intBuffer, zaxisNint, CDI_DATATYPE_INT, context);
1450   serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1451                   &d, 1, CDI_DATATYPE_UINT32, context);
1452 
1453   xassert(cdiCheckSum(CDI_DATATYPE_INT, zaxisNint, intBuffer) == d);
1454 
1455   zaxisInit();
1456 
1457   zaxis_t *zaxisP
1458     = zaxisNewEntry(force_id ? namespaceAdaptKey(intBuffer[0], originNamespace)
1459                     : CDI_UNDEFID);
1460 
1461   zaxisP->type      = intBuffer[1];
1462   zaxisP->size      = intBuffer[2];
1463   zaxisP->direction = intBuffer[3];
1464   zaxisP->vctsize   = intBuffer[4];
1465   memberMask        = intBuffer[5];
1466 
1467   if (memberMask & vals)
1468     {
1469       int size = zaxisP->size;
1470       xassert(size >= 0);
1471 
1472       zaxisP->vals = (double *) Malloc((size_t)size * sizeof (double));
1473       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1474                       zaxisP->vals, size, CDI_DATATYPE_FLT64, context);
1475       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1476                       &d, 1, CDI_DATATYPE_UINT32, context);
1477       xassert(cdiCheckSum(CDI_DATATYPE_FLT, size, zaxisP->vals) == d);
1478     }
1479 
1480   if (memberMask & lbounds)
1481     {
1482       int size = zaxisP->size;
1483       xassert(size >= 0);
1484 
1485       zaxisP->lbounds = (double *) Malloc((size_t)size * sizeof (double));
1486       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1487                       zaxisP->lbounds, size, CDI_DATATYPE_FLT64, context);
1488       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1489                       &d, 1, CDI_DATATYPE_UINT32, context);
1490       xassert(cdiCheckSum(CDI_DATATYPE_FLT, size, zaxisP->lbounds) == d);
1491     }
1492 
1493   if (memberMask & ubounds)
1494     {
1495       int size = zaxisP->size;
1496       xassert(size >= 0);
1497 
1498       zaxisP->ubounds = (double *) Malloc((size_t)size * sizeof (double));
1499       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1500                       zaxisP->ubounds, size, CDI_DATATYPE_FLT64, context);
1501       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1502                       &d, 1, CDI_DATATYPE_UINT32, context);
1503       xassert(cdiCheckSum(CDI_DATATYPE_FLT, size, zaxisP->ubounds) == d);
1504     }
1505 
1506   if (memberMask & weights)
1507     {
1508       int size = zaxisP->size;
1509       xassert(size >= 0);
1510 
1511       zaxisP->weights = (double *) Malloc((size_t)size * sizeof (double));
1512       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1513                       zaxisP->weights, size, CDI_DATATYPE_FLT64, context);
1514       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1515                       &d, 1, CDI_DATATYPE_UINT32, context);
1516       xassert(cdiCheckSum(CDI_DATATYPE_FLT, size, zaxisP->weights) == d);
1517     }
1518 
1519   if (memberMask & vct)
1520     {
1521       int size = zaxisP->vctsize;
1522       xassert(size >= 0);
1523 
1524       zaxisP->vct = (double *) Malloc((size_t)size * sizeof (double));
1525       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1526                       zaxisP->vct, size, CDI_DATATYPE_FLT64, context);
1527       serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1528                       &d, 1, CDI_DATATYPE_UINT32, context);
1529       xassert(cdiCheckSum(CDI_DATATYPE_FLT64, size, zaxisP->vct) == d);
1530     }
1531 
1532   serializeKeysUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos, &zaxisP->keys, context);
1533 
1534   serializeUnpack(unpackBuffer, unpackBufferSize, unpackBufferPos,
1535                   &zaxisP->positive, 1, CDI_DATATYPE_UINT, context);
1536 
1537   reshSetStatus(zaxisP->self, &zaxisOps,
1538                 reshGetStatus(zaxisP->self, &zaxisOps) & ~RESH_SYNC_BIT);
1539 }
1540 
1541 static void
zaxisPack(void * voidP,void * packBuffer,int packBufferSize,int * packBufferPos,void * context)1542 zaxisPack(void * voidP, void * packBuffer, int packBufferSize,
1543           int * packBufferPos, void *context)
1544 {
1545   zaxis_t   * zaxisP = ( zaxis_t * ) voidP;
1546   int intBuffer[zaxisNint];
1547   int memberMask;
1548   uint32_t d;
1549 
1550   intBuffer[0]  = zaxisP->self;
1551   intBuffer[1]  = zaxisP->type;
1552   intBuffer[2]  = zaxisP->size;
1553   intBuffer[3]  = zaxisP->direction;
1554   intBuffer[4]  = zaxisP->vctsize;
1555   intBuffer[5]  = memberMask = zaxisGetMemberMask ( zaxisP );
1556 
1557   serializePack(intBuffer, zaxisNint, CDI_DATATYPE_INT,
1558                 packBuffer, packBufferSize, packBufferPos, context);
1559   d = cdiCheckSum(CDI_DATATYPE_INT, zaxisNint, intBuffer);
1560   serializePack(&d, 1, CDI_DATATYPE_UINT32,
1561                 packBuffer, packBufferSize, packBufferPos, context);
1562 
1563 
1564   if ( memberMask & vals )
1565     {
1566       xassert(zaxisP->size);
1567       serializePack(zaxisP->vals, zaxisP->size, CDI_DATATYPE_FLT64,
1568                     packBuffer, packBufferSize, packBufferPos, context);
1569       d = cdiCheckSum(CDI_DATATYPE_FLT, zaxisP->size, zaxisP->vals );
1570       serializePack(&d, 1, CDI_DATATYPE_UINT32,
1571                     packBuffer, packBufferSize, packBufferPos, context);
1572     }
1573 
1574   if (memberMask & lbounds)
1575     {
1576       xassert(zaxisP->size);
1577       serializePack(zaxisP->lbounds, zaxisP->size, CDI_DATATYPE_FLT64,
1578                     packBuffer, packBufferSize, packBufferPos, context);
1579       d = cdiCheckSum(CDI_DATATYPE_FLT, zaxisP->size, zaxisP->lbounds);
1580       serializePack(&d, 1, CDI_DATATYPE_UINT32,
1581                     packBuffer, packBufferSize, packBufferPos, context);
1582     }
1583 
1584   if (memberMask & ubounds)
1585     {
1586       xassert(zaxisP->size);
1587 
1588       serializePack(zaxisP->ubounds, zaxisP->size, CDI_DATATYPE_FLT64,
1589                     packBuffer, packBufferSize, packBufferPos, context);
1590       d = cdiCheckSum(CDI_DATATYPE_FLT, zaxisP->size, zaxisP->ubounds);
1591       serializePack(&d, 1, CDI_DATATYPE_UINT32,
1592                     packBuffer, packBufferSize, packBufferPos, context);
1593     }
1594 
1595   if (memberMask & weights)
1596     {
1597       xassert(zaxisP->size);
1598 
1599       serializePack(zaxisP->weights, zaxisP->size, CDI_DATATYPE_FLT64,
1600                     packBuffer, packBufferSize, packBufferPos, context);
1601       d = cdiCheckSum(CDI_DATATYPE_FLT, zaxisP->size, zaxisP->weights);
1602       serializePack(&d, 1, CDI_DATATYPE_UINT32,
1603                     packBuffer, packBufferSize, packBufferPos, context);
1604     }
1605 
1606   if (memberMask & vct)
1607     {
1608       xassert(zaxisP->vctsize);
1609 
1610       serializePack(zaxisP->vct, zaxisP->vctsize, CDI_DATATYPE_FLT64,
1611                     packBuffer, packBufferSize, packBufferPos, context);
1612       d = cdiCheckSum(CDI_DATATYPE_FLT64, zaxisP->vctsize, zaxisP->vct);
1613       serializePack(&d, 1, CDI_DATATYPE_UINT32,
1614                     packBuffer, packBufferSize, packBufferPos, context);
1615     }
1616 
1617   serializeKeysPack(&zaxisP->keys, packBuffer, packBufferSize, packBufferPos, context);
1618 
1619   serializePack(&zaxisP->positive, 1, CDI_DATATYPE_UINT,
1620                 packBuffer, packBufferSize, packBufferPos, context);
1621 }
1622 
1623 
cdiZaxisGetIndexList(unsigned nzaxis,int * zaxisResHs)1624 void cdiZaxisGetIndexList(unsigned nzaxis, int *zaxisResHs)
1625 {
1626   reshGetResHListOfType(nzaxis, zaxisResHs, &zaxisOps);
1627 }
1628 
1629 /*
1630  * Local Variables:
1631  * c-file-style: "Java"
1632  * c-basic-offset: 2
1633  * indent-tabs-mode: nil
1634  * show-trailing-whitespace: t
1635  * require-trailing-newline: t
1636  * End:
1637  */
1638