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

Thomas Jahns's avatar
Thomas Jahns committed
5
#include <assert.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
#include <string.h>
7
#include <float.h>  /* FLT_EPSILON */
8
#include <limits.h> /* INT_MAX     */
9

Uwe Schulzweida's avatar
Uwe Schulzweida committed
10
11
#include "dmemory.h"
#include "cdi.h"
12
#include "cdi_cksum.h"
13
#include "cdi_int.h"
14
#include "cdi_uuid.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
15
#include "grid.h"
16
#include "gaussgrid.h"
17
#include "resource_handle.h"
18
#include "resource_unpack.h"
19
#include "namespace.h"
20
#include "serialize.h"
21
22
#include "vlist.h"

23
double grid_missval = -9999.;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
24

25
26
27
/* the value in the second pair of brackets must match the length of
 * the longest string (including terminating NUL) */
static const char Grids[][17] = {
28
29
30
31
32
33
34
35
36
  /*  0 */  "undefined",
  /*  1 */  "generic",
  /*  2 */  "gaussian",
  /*  3 */  "gaussian reduced",
  /*  4 */  "lonlat",
  /*  5 */  "spectral",
  /*  6 */  "fourier",
  /*  7 */  "gme",
  /*  8 */  "trajectory",
37
  /*  9 */  "unstructured",
38
39
  /* 10 */  "curvilinear",
  /* 11 */  "lcc",
40
  /* 12 */  "projection",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
41
42
};

43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/* must match table below */
enum xystdname_idx {
  grid_xystdname_grid_latlon,
  grid_xystdname_latlon,
  grid_xystdname_projection,
};
static const char xystdname_tab[][2][24] = {
  [grid_xystdname_grid_latlon] = { "grid_longitude",
                                   "grid_latitude" },
  [grid_xystdname_latlon] = { "longitude",
                              "latitude" },
  [grid_xystdname_projection] = { "projection_x_coordinate",
                                  "projection_y_coordinate" },

};


Uwe Schulzweida's avatar
Uwe Schulzweida committed
60

61
62
63
static int    gridCompareP    ( void * gridptr1, void * gridptr2 );
static void   gridDestroyP    ( void * gridptr );
static void   gridPrintP      ( void * gridptr, FILE * fp );
64
static int    gridGetPackSize ( void * gridptr, void *context);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
65
static void   gridPack        ( void * gridptr, void * buff, int size, int *position, void *context);
Deike Kleberg's avatar
minimal    
Deike Kleberg committed
66
static int    gridTxCode      ( void );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
67

68
static const resOps gridOps = {
69
70
71
72
73
74
  gridCompareP,
  gridDestroyP,
  gridPrintP,
  gridGetPackSize,
  gridPack,
  gridTxCode
75
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
76

77
static int  GRID_Debug = 0;   /* If set to 1, debugging */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
78

Uwe Schulzweida's avatar
Uwe Schulzweida committed
79

80
grid_t *grid_to_pointer(int gridID)
81
82
83
{
  return (grid_t *)reshGetVal(gridID, &gridOps);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
84

85
#define gridMark4Update(gridID) reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
86

87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
static
bool cdiInqAttConvertedToFloat(int gridID, int atttype, const char *attname, int attlen, double *attflt)
{
  bool status = true;

  if ( atttype == CDI_DATATYPE_INT32 )
    {
      int attint[attlen];
      cdiInqAttInt(gridID, CDI_GLOBAL, attname, attlen, attint);
      for ( int i = 0; i < attlen; ++i ) attflt[i] = (double)attint[i];
    }
  else if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
    {
      cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, attflt);
    }
  else
    {
      status = false;
    }

  return status;
}

110

Deike Kleberg's avatar
Deike Kleberg committed
111
void grid_init(grid_t *gridptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
{
113
114
115
  gridptr->self          = CDI_UNDEFID;
  gridptr->type          = CDI_UNDEFID;
  gridptr->proj          = CDI_UNDEFID;
116
  gridptr->projtype      = CDI_UNDEFID;
117
118
  gridptr->mask          = NULL;
  gridptr->mask_gme      = NULL;
119
120
121
122
  gridptr->x.vals        = NULL;
  gridptr->y.vals        = NULL;
  gridptr->x.bounds      = NULL;
  gridptr->y.bounds      = NULL;
123
  gridptr->area          = NULL;
124
125
  gridptr->rowlon        = NULL;
  gridptr->nrowlon       = 0;
126

127
128
129
130
131
132
  gridptr->x.first       = 0.0;
  gridptr->x.last        = 0.0;
  gridptr->x.inc         = 0.0;
  gridptr->y.first       = 0.0;
  gridptr->y.last        = 0.0;
  gridptr->y.inc         = 0.0;
133

134
135
136
137
  gridptr->gme.nd        = 0;
  gridptr->gme.ni        = 0;
  gridptr->gme.ni2       = 0;
  gridptr->gme.ni3       = 0;
138

139
140
141
142
143
144
145
  gridptr->trunc         = 0;
  gridptr->nvertex       = 0;
  gridptr->number        = 0;
  gridptr->position      = 0;
  gridptr->reference     = NULL;
  gridptr->prec          = 0;
  gridptr->size          = 0;
146
147
  gridptr->x.size        = 0;
  gridptr->y.size        = 0;
148
  gridptr->np            = 0;
149
150
  gridptr->x.flag        = 0;
  gridptr->y.flag        = 0;
151
  gridptr->isCyclic      = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
152

153
  gridptr->lcomplex      = false;
154
155
156
157
158
159
160
161
162
163
164
  gridptr->hasdims       = true;
  gridptr->x.dimname[0]  = 0;
  gridptr->y.dimname[0]  = 0;
  gridptr->x.name[0]     = 0;
  gridptr->y.name[0]     = 0;
  gridptr->x.longname[0] = 0;
  gridptr->y.longname[0] = 0;
  gridptr->x.units[0]    = 0;
  gridptr->y.units[0]    = 0;
  gridptr->x.stdname     = NULL;
  gridptr->y.stdname     = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
165
166
167
  gridptr->vdimname[0]   = 0;
  gridptr->mapname[0]    = 0;
  gridptr->mapping[0]    = 0;
Thomas Jahns's avatar
Thomas Jahns committed
168
  memset(gridptr->uuid, 0, CDI_UUID_SIZE);
169
170
  gridptr->name          = NULL;
  gridptr->vtable        = &cdiGridVtable;
171
  gridptr->atts.nalloc   = MAX_ATTRIBUTES;
172
  gridptr->atts.nelems   = 0;
173
  gridptr->uvRelativeToGrid      = 0;   // Some models deliver wind U,V relative to the grid-cell
174
175
176
177
178
179
180
181
182
183
  gridptr->iScansNegatively      = 0;
  gridptr->jScansPositively      = 1;
  gridptr->jPointsAreConsecutive = 0;
  gridptr->scanningMode          = 128*gridptr->iScansNegatively + 64*gridptr->jScansPositively + 32*gridptr->jPointsAreConsecutive;
  /* scanningMode  = 128 * iScansNegatively + 64 * jScansPositively + 32 * jPointsAreConsecutive;
               64  = 128 * 0                + 64 *        1         + 32 * 0
               00  = 128 * 0                + 64 *        0         + 32 * 0
               96  = 128 * 0                + 64 *        1         + 32 * 1
     Default / implicit scanning mode is 64:
                        i and j scan positively, i points are consecutive (row-major)        */
Uwe Schulzweida's avatar
Uwe Schulzweida committed
184
185
}

186

187
188
static
void grid_free_components(grid_t *gridptr)
Deike Kleberg's avatar
Deike Kleberg committed
189
{
190
  void *p2free[] = { gridptr->mask, gridptr->mask_gme,
191
192
193
194
195
                     gridptr->x.vals, gridptr->y.vals,
                     gridptr->x.bounds, gridptr->y.bounds,
                     gridptr->rowlon, gridptr->area,
                     gridptr->reference, gridptr->name};

196
  for ( size_t i = 0; i < sizeof(p2free)/sizeof(p2free[0]); ++i )
197
    if ( p2free[i] ) Free(p2free[i]);
198
}
Deike Kleberg's avatar
Deike Kleberg committed
199

200
201
202
void grid_free(grid_t *gridptr)
{
  grid_free_components(gridptr);
Deike Kleberg's avatar
Deike Kleberg committed
203
204
205
  grid_init(gridptr);
}

206
207
static
grid_t *gridNewEntry(cdiResH resH)
208
{
209
  grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t));
210
  grid_init(gridptr);
211

212
  if ( resH == CDI_UNDEFID )
213
214
215
216
217
218
    gridptr->self = reshPut(gridptr, &gridOps);
  else
    {
      gridptr->self = resH;
      reshReplace(resH, gridptr, &gridOps);
    }
219

220
  return gridptr;
221
222
}

223
static
224
void gridInit(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
225
{
226
  static bool gridInitialized = false;
227
  if ( gridInitialized ) return;
228
  gridInitialized = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
229

Uwe Schulzweida's avatar
Uwe Schulzweida committed
230
  const char *env = getenv("GRID_DEBUG");
231
  if ( env ) GRID_Debug = atoi(env);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
232
233
}

234
235
static
void grid_copy_base_scalar_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
236
{
Thomas Jahns's avatar
Thomas Jahns committed
237
238
  memcpy(gridptrDup, gridptrOrig, sizeof(grid_t));
  gridptrDup->self = CDI_UNDEFID;
239
  if ( gridptrOrig->reference )
Thomas Jahns's avatar
Thomas Jahns committed
240
241
242
    gridptrDup->reference = strdupx(gridptrOrig->reference);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
243

244
245
static
grid_t *grid_copy_base(grid_t *gridptrOrig)
Thomas Jahns's avatar
Thomas Jahns committed
246
247
248
249
250
{
  grid_t *gridptrDup = (grid_t *)Malloc(sizeof (*gridptrDup));
  gridptrOrig->vtable->copyScalarFields(gridptrOrig, gridptrDup);
  gridptrOrig->vtable->copyArrayFields(gridptrOrig, gridptrDup);
  return gridptrDup;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
251
252
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
253

254
unsigned cdiGridCount(void)
Thomas Jahns's avatar
Thomas Jahns committed
255
{
256
  return reshCountType(&gridOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
257
258
}

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
static inline
void gridSetString(char *gridstrname, const char *name, size_t len)
{
  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
  strncpy(gridstrname, name, len);
  gridstrname[len - 1] = 0;
}

static inline
void gridGetString(char *name, const char *gridstrname, size_t len)
{
  if ( len > CDI_MAX_NAME ) len = CDI_MAX_NAME;
  strncpy(name, gridstrname, len);
  name[len - 1] = 0;
}

275
276
static inline
void gridSetName(char *gridstrname, const char *name)
277
{
278
279
  strncpy(gridstrname, name, CDI_MAX_NAME);
  gridstrname[CDI_MAX_NAME - 1] = 0;
280
281
}

282
283

void cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
284
285
286
287
{
  gridptr->type = gridtype;
  gridptr->size = size;

288
289
290
  if      ( gridtype == GRID_CURVILINEAR  ) gridptr->nvertex = 4;
  else if ( gridtype == GRID_UNSTRUCTURED ) gridptr->x.size = size;

291
292
293
294
295
296
  switch (gridtype)
    {
    case GRID_LONLAT:
    case GRID_GAUSSIAN:
    case GRID_GAUSSIAN_REDUCED:
    case GRID_TRAJECTORY:
297
298
299
    case GRID_CURVILINEAR:
    case GRID_UNSTRUCTURED:
    case GRID_GME:
300
301
302
      {
        if ( gridtype == GRID_TRAJECTORY )
          {
303
304
            if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "tlon");
            if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "tlat");
305
306
307
          }
        else
          {
308
309
            if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "lon");
            if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "lat");
310
          }
311

312
313
        gridSetName(gridptr->x.longname, "longitude");
        gridSetName(gridptr->y.longname, "latitude");
314

315
316
        gridptr->x.stdname = xystdname_tab[grid_xystdname_latlon][0];
        gridptr->y.stdname = xystdname_tab[grid_xystdname_latlon][1];
317
318
        gridSetName(gridptr->x.units, "degrees_east");
        gridSetName(gridptr->y.units, "degrees_north");
319

320
321
322
        break;
      }
    case GRID_GENERIC:
323
    case GRID_PROJECTION:
324
      {
325
326
        if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "x");
        if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "y");
327
328
329
        if ( gridtype == GRID_PROJECTION )
          {
            gridSetName(gridptr->mapname, "Projection");
330

331
332
333
334
335
            gridptr->x.stdname = xystdname_tab[grid_xystdname_projection][0];
            gridptr->y.stdname = xystdname_tab[grid_xystdname_projection][1];
            gridSetName(gridptr->x.units, "m");
            gridSetName(gridptr->y.units, "m");
          }
336
337
338
339
340
341
        break;
      }
    }
}


342
// used also in CDO
343
void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *restrict xvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
344
{
345
  if ( (! (fabs(xinc) > 0)) && xsize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
346
347
    {
      if ( xfirst >= xlast )
Thomas Jahns's avatar
Thomas Jahns committed
348
349
350
351
        {
          while ( xfirst >= xlast ) xlast += 360;
          xinc = (xlast-xfirst)/(xsize);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
352
      else
Thomas Jahns's avatar
Thomas Jahns committed
353
354
355
        {
          xinc = (xlast-xfirst)/(xsize-1);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
356
357
    }

358
  for ( int i = 0; i < xsize; ++i )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
359
360
361
    xvals[i] = xfirst + i*xinc;
}

362
static
363
void calc_gaussgrid(double *restrict yvals, int ysize, double yfirst, double ylast)
364
{
365
  double *restrict yw = (double *) Malloc((size_t)ysize * sizeof(double));
366
  gaussaw(yvals, yw, (size_t)ysize);
367
  Free(yw);
368
  for (int i = 0; i < ysize; i++ )
369
370
371
372
    yvals[i] = asin(yvals[i])/M_PI*180.0;

  if ( yfirst < ylast && yfirst > -90.0 && ylast < 90.0 )
    {
373
374
      int yhsize = ysize/2;
      for (int i = 0; i < yhsize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
375
        {
376
          double ytmp = yvals[i];
Thomas Jahns's avatar
Thomas Jahns committed
377
378
379
          yvals[i] = yvals[ysize-i-1];
          yvals[ysize-i-1] = ytmp;
        }
380
381
382
    }
}

383
// used also in CDO
Thomas Jahns's avatar
Thomas Jahns committed
384
void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
385
{
386
  const double deleps = 0.002;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
387
388
389
390

  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
    {
      if ( ysize > 2 )
Deike Kleberg's avatar
Deike Kleberg committed
391
392
393
394
395
396
	{
	  calc_gaussgrid(yvals, ysize, yfirst, ylast);

	  if ( ! (IS_EQUAL(yfirst, 0) && IS_EQUAL(ylast, 0)) )
	    if ( fabs(yvals[0] - yfirst) > deleps || fabs(yvals[ysize-1] - ylast) > deleps )
	      {
397
		double *restrict ytmp = NULL;
Deike Kleberg's avatar
Deike Kleberg committed
398
		int nstart, lfound = 0;
399
		int ny = (int) (180./(fabs(ylast-yfirst)/(ysize-1)) + 0.5);
Deike Kleberg's avatar
Deike Kleberg committed
400
401
402
		ny -= ny%2;
		if ( ny > ysize && ny < 4096 )
		  {
403
		    ytmp = (double *) Malloc((size_t)ny * sizeof (double));
Deike Kleberg's avatar
Deike Kleberg committed
404
		    calc_gaussgrid(ytmp, ny, yfirst, ylast);
405
406
407
408
409
410
                    {
                      int i;
                      for ( i = 0; i < (ny-ysize); i++ )
                        if ( fabs(ytmp[i] - yfirst) < deleps ) break;
                      nstart = i;
                    }
Deike Kleberg's avatar
Deike Kleberg committed
411

412
413
		    lfound = (nstart+ysize-1) < ny
                      && fabs(ytmp[nstart+ysize-1] - ylast) < deleps;
414
415
416
417
                    if ( lfound )
                      {
                        for (int i = 0; i < ysize; i++) yvals[i] = ytmp[i+nstart];
                      }
Deike Kleberg's avatar
Deike Kleberg committed
418
419
		  }

420
		if ( !lfound )
Deike Kleberg's avatar
Deike Kleberg committed
421
		  {
422
		    Warning("Cannot calculate gaussian latitudes for lat1 = %g latn = %g!", yfirst, ylast);
423
		    for (int i = 0; i < ysize; i++ ) yvals[i] = 0;
Deike Kleberg's avatar
Deike Kleberg committed
424
425
426
427
		    yvals[0] = yfirst;
		    yvals[ysize-1] = ylast;
		  }

428
		if ( ytmp ) Free(ytmp);
Deike Kleberg's avatar
Deike Kleberg committed
429
430
	      }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
431
      else
Thomas Jahns's avatar
Thomas Jahns committed
432
433
434
435
        {
          yvals[0] = yfirst;
          yvals[ysize-1] = ylast;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
436
437
438
439
    }
  /*     else if ( gridtype == GRID_LONLAT || gridtype == GRID_GENERIC ) */
  else
    {
440
      if ( (! (fabs(yinc) > 0)) && ysize > 1 )
Thomas Jahns's avatar
Thomas Jahns committed
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
        {
          if ( IS_EQUAL(yfirst, ylast) && IS_NOT_EQUAL(yfirst, 0) ) ylast *= -1;

          if ( yfirst > ylast )
            yinc = (yfirst-ylast)/(ysize-1);
          else if ( yfirst < ylast )
            yinc = (ylast-yfirst)/(ysize-1);
          else
            {
              if ( ysize%2 != 0 )
                {
                  yinc = 180.0/(ysize-1);
                  yfirst = -90;
                }
              else
                {
                  yinc = 180.0/ysize;
                  yfirst = -90 + yinc/2;
                }
            }
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
462
463
464

      if ( yfirst > ylast && yinc > 0 ) yinc = -yinc;

465
      for (int i = 0; i < ysize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
466
        yvals[i] = yfirst + i*yinc;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
467
468
469
    }
  /*
    else
470
    Error("unable to calculate values for %s grid!", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
471
472
473
474
  */
}

/*
475
@Function  gridCreate
476
@Title     Create a horizontal Grid
Uwe Schulzweida's avatar
Uwe Schulzweida committed
477

478
@Prototype int gridCreate(int gridtype, int size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
479
480
@Parameter
    @Item  gridtype  The type of the grid, one of the set of predefined CDI grid types.
481
                     The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
482
                     @func{GRID_LONLAT}, @func{GRID_PROJECTION}, @func{GRID_SPECTRAL},
483
                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
485
486
    @Item  size      Number of gridpoints.

@Description
487
The function @func{gridCreate} creates a horizontal Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
489

@Result
490
@func{gridCreate} returns an identifier to the Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
491
492

@Example
493
Here is an example using @func{gridCreate} to create a regular lon/lat Grid:
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494
495

@Source
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
497
#include "cdi.h"
   ...
498
499
#define  nlon  12
#define  nlat   6
Uwe Schulzweida's avatar
Uwe Schulzweida committed
500
   ...
501
502
double lons[nlon] = {0, 30, 60, 90, 120, 150, 180, 210, 240, 270, 300, 330};
double lats[nlat] = {-75, -45, -15, 15, 45, 75};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503
504
int gridID;
   ...
505
506
507
gridID = gridCreate(GRID_LONLAT, nlon*nlat);
gridDefXsize(gridID, nlon);
gridDefYsize(gridID, nlat);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
510
511
gridDefXvals(gridID, lons);
gridDefYvals(gridID, lats);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
512
513
@EndFunction
*/
514
int gridCreate(int gridtype, int size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
515
{
516
  if ( CDI_Debug ) Message("gridtype=%s  size=%d", gridNamePtr(gridtype), size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517

518
  if ( size < 0 || size > INT_MAX ) Error("Grid size (%d) out of bounds (0 - %d)!", size, INT_MAX);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
519

520
  gridInit();
521

Uwe Schulzweida's avatar
Uwe Schulzweida committed
522
  grid_t *gridptr = gridNewEntry(CDI_UNDEFID);
523
  if ( ! gridptr ) Error("No memory");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
524

Uwe Schulzweida's avatar
Uwe Schulzweida committed
525
  int gridID = gridptr->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526

527
  if ( CDI_Debug ) Message("gridID: %d", gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528

529
  cdiGridTypeInit(gridptr, gridtype, size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
530

Uwe Schulzweida's avatar
Uwe Schulzweida committed
531
  return gridID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
534
535
static
void gridDestroyKernel( grid_t * gridptr )
536
{
Deike Kleberg's avatar
Deike Kleberg committed
537
  xassert ( gridptr );
538

539
  int id = gridptr->self;
540

541
  grid_free_components(gridptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
  Free( gridptr );
543

544
  reshRemove ( id, &gridOps );
545
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546

547
548
549
550
551
552
/*
@Function  gridDestroy
@Title     Destroy a horizontal Grid

@Prototype void gridDestroy(int gridID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
553
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
554
555
556
557
558

@EndFunction
*/
void gridDestroy(int gridID)
{
559
  grid_t *gridptr = grid_to_pointer(gridID);
560
  gridptr->vtable->destroy(gridptr);
561
562
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
563
564
static
void gridDestroyP(void * gridptr)
565
{
566
  ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
567
568
569
}


570
const char *gridNamePtr(int gridtype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
571
{
572
  int size = (int) (sizeof(Grids)/sizeof(Grids[0]));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573

Uwe Schulzweida's avatar
Uwe Schulzweida committed
574
  const char *name = (gridtype >= 0 && gridtype < size) ? Grids[gridtype] : Grids[GRID_GENERIC];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
575

Uwe Schulzweida's avatar
Uwe Schulzweida committed
576
  return name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
577
578
579
580
581
582
583
584
}


void gridName(int gridtype, char *gridname)
{
  strcpy(gridname, gridNamePtr(gridtype));
}

585
static
586
void *grid_key_to_ptr(grid_t *gridptr, int key)
587
{
588
  void *keyptr = NULL;
589
590
591

  switch (key)
    {
592
593
594
595
596
597
598
599
600
    case CDI_KEY_XNAME:      keyptr = (void*)gridptr->x.name; break;
    case CDI_KEY_XLONGNAME:  keyptr = (void*)gridptr->x.longname; break;
    case CDI_KEY_XUNITS:     keyptr = (void*)gridptr->x.units; break;
    case CDI_KEY_YNAME:      keyptr = (void*)gridptr->y.name; break;
    case CDI_KEY_YLONGNAME:  keyptr = (void*)gridptr->y.longname; break;
    case CDI_KEY_YUNITS:     keyptr = (void*)gridptr->y.units; break;
    case CDI_KEY_XDIMNAME:   keyptr = (void*)gridptr->x.dimname; break;
    case CDI_KEY_YDIMNAME:   keyptr = (void*)gridptr->y.dimname; break;
    case CDI_KEY_VDIMNAME:   keyptr = (void*)gridptr->vdimname; break;
601
602
    case CDI_KEY_MAPPING:    keyptr = (void*)gridptr->mapname; break;
    case CDI_KEY_MAPNAME:    keyptr = (void*)gridptr->mapping; break;
603
604
    }

605
  return keyptr;
606
607
}

608
/*
609
@Function  cdiGridDefKeyStr
610
611
@Title     Define a CDI grid string value from a key

612
@Prototype int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg)
613
614
615
616
617
618
619
@Parameter
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  key      The key to be searched
    @Item  size     The allocated length of the string on input
    @Item  mesg     The address of a string where the data will be read

@Description
620
The function @func{cdiGridDefKeyStr} defines a CDI grid string value from a key.
621
622

@Result
623
@func{cdiGridDefKeyStr} returns 0 if OK and integer value on error.
624
625
626

@EndFunction
*/
627
int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg)
628
{
629
  if ( size < 1 || mesg == NULL || *mesg == 0 ) return -1;
630

631
  grid_t *gridptr = grid_to_pointer(gridID);
632

633
634
  char *keyptr = (char*)grid_key_to_ptr(gridptr, key);
  if ( keyptr == NULL )
635
636
637
638
639
    {
      Warning("CDI grid string key %d not supported!", key);
      return -1;
    }

640
  gridSetString(keyptr, mesg, (size_t)size);
641
642
643
644
645
646
  gridMark4Update(gridID);

  return 0;
}

/*
647
@Function  cdiGridInqKeyStr
648
649
@Title     Get a CDI grid string value from a key

650
@Prototype int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
651
652
653
654
655
656
657
658
659
660
@Parameter
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  key      The key to be searched.
    @Item  size     The allocated length of the string on input.
    @Item  mesg     The address of a string where the data will be retrieved.
                    The caller must allocate space for the returned string.
                    The maximum possible length, in characters, of the string
                    is given by the predefined constant @func{CDI_MAX_NAME}.

@Description
661
The function @func{cdiGridInqKeyStr} return a CDI grid string value from a key.
662
663

@Result
664
@func{cdiGridInqKeyStr} returns 0 if OK and integer value on error.
665
666
667

@EndFunction
*/
668
int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
669
{
670
  if ( size < 1 || mesg == NULL ) return -1;
671

672
  grid_t *gridptr = grid_to_pointer(gridID);
673
674
  const char *keyptr = (const char*)grid_key_to_ptr(gridptr, key);
  if ( keyptr == NULL)
675
676
677
678
679
    {
      Warning("CDI grid string key %d not supported!", key);
      return -1;
    }

680
  gridGetString(mesg, keyptr, (size_t)size);
681
682
683
684

  return 0;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
686
687
688
689
690
/*
@Function  gridDefXname
@Title     Define the name of a X-axis

@Prototype void gridDefXname(int gridID, const char *name)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
691
692
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  name     Name of the X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
694

@Description
695
The function @func{gridDefXname} defines the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
696
697
698

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
void gridDefXname(int gridID, const char *xname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
700
{
701
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
703
704
705
706
707
708
709
}

/*
@Function  gridDefXlongname
@Title     Define the longname of a X-axis

@Prototype void gridDefXlongname(int gridID, const char *longname)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
710
711
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  longname Longname of the X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
712
713

@Description
714
The function @func{gridDefXlongname} defines the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
715
716
717

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
718
void gridDefXlongname(int gridID, const char *xlongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
{
720
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
721
722
723
724
725
726
727
728
}

/*
@Function  gridDefXunits
@Title     Define the units of a X-axis

@Prototype void gridDefXunits(int gridID, const char *units)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
729
730
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  units    Units of the X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
731
732

@Description
733
The function @func{gridDefXunits} defines the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
735
736

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
737
void gridDefXunits(int gridID, const char *xunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
{
739
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
740
741
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
742
743
744
745
746
747
/*
@Function  gridDefYname
@Title     Define the name of a Y-axis

@Prototype void gridDefYname(int gridID, const char *name)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
748
749
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  name     Name of the Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
750
751

@Description
752
The function @func{gridDefYname} defines the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
754
755

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
756
void gridDefYname(int gridID, const char *yname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
{
758
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
759
760
761
762
763
764
765
766
}

/*
@Function  gridDefYlongname
@Title     Define the longname of a Y-axis

@Prototype void gridDefYlongname(int gridID, const char *longname)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
767
768
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  longname Longname of the Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
769
770

@Description
771
The function @func{gridDefYlongname} defines the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
772
773
774

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
775
void gridDefYlongname(int gridID, const char *ylongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
776
{
777
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
778
779
780
781
782
783
784
785
}

/*
@Function  gridDefYunits
@Title     Define the units of a Y-axis

@Prototype void gridDefYunits(int gridID, const char *units)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
786
787
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  units    Units of the Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
788
789

@Description
790
The function @func{gridDefYunits} defines the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
792
793

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
794
void gridDefYunits(int gridID, const char *yunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
795
{
796
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
797
798
799
800
801
802
}

/*
@Function  gridInqXname
@Title     Get the name of a X-axis

Deike Kleberg's avatar
Deike Kleberg committed
803
@Prototype void gridInqXname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
804
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
806
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  name     Name of the X-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
807
                    returned string. The maximum possible length, in characters, of
808
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
809
810

@Description
811
The function @func{gridInqXname} returns the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
813

@Result
814
@func{gridInqXname} returns the name of the X-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
815
816
817
818
819

@EndFunction
*/
void gridInqXname(int gridID, char *xname)
{
820
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
821
822
823
824
825
826
}

/*
@Function  gridInqXlongname
@Title     Get the longname of a X-axis

Deike Kleberg's avatar
Deike Kleberg committed
827
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
830
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  longname Longname of the X-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
831
                    returned string. The maximum possible length, in characters, of
832
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
833
834

@Description
835
The function @func{gridInqXlongname} returns the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
836
837

@Result
838
@func{gridInqXlongname} returns the longname of the X-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
839
840
841
842
843

@EndFunction
*/
void gridInqXlongname(int gridID, char *xlongname)
{
844
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846
847
848
849
850
}

/*
@Function  gridInqXunits
@Title     Get the units of a X-axis

Deike Kleberg's avatar
Deike Kleberg committed
851
@Prototype void gridInqXunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
852
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
854
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  units    Units of the X-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
855
                    returned string. The maximum possible length, in characters, of
856
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
858

@Description
859
The function @func{gridInqXunits} returns the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
860
861

@Result
862
@func{gridInqXunits} returns the units of the X-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
863
864
865
866
867

@EndFunction
*/
void gridInqXunits(int gridID, char *xunits)
{
868
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
870
871
872
873
}


void gridInqXstdname(int gridID, char *xstdname)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
874
875
876
877
878
879
  if ( xstdname )
    {
      xstdname[0] = 0;
      grid_t *gridptr = grid_to_pointer(gridID);
      if ( gridptr->x.stdname ) strcpy(xstdname, gridptr->x.stdname);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
880
881
882
883
884
885
}

/*
@Function  gridInqYname
@Title     Get the name of a Y-axis

Deike Kleberg's avatar
Deike Kleberg committed
886
@Prototype void gridInqYname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
888
889
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  name     Name of the Y-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
890
                    returned string. The maximum possible length, in characters, of
891
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
892
893

@Description
894
The function @func{gridInqYname} returns the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
895
896

@Result
897
@func{gridInqYname} returns the name of the Y-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
898
899
900
901
902

@EndFunction
*/
void gridInqYname(int gridID, char *yname)
{
903
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
904
905
906
907
908
909
}

/*
@Function  gridInqYlongname
@Title     Get the longname of a Y-axis

910
@Prototype void gridInqYlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
911
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
913
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  longname Longname of the Y-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
914
                    returned string. The maximum possible length, in characters, of
915
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
916
917

@Description
918
The function @func{gridInqYlongname} returns the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
920

@Result
921
@func{gridInqYlongname} returns the longname of the Y-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
922
923
924
925
926

@EndFunction
*/
void gridInqYlongname(int gridID, char *ylongname)
{
927
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
928
929
930
931
932
933
}

/*
@Function  gridInqYunits
@Title     Get the units of a Y-axis

Deike Kleberg's avatar
Deike Kleberg committed
934
@Prototype void gridInqYunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
935
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
936
937
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  units    Units of the Y-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
938
                    returned string. The maximum possible length, in characters, of
939
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
940
941

@Description
942
The function @func{gridInqYunits} returns the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
943
944

@Result
945
@func{gridInqYunits} returns the units of the Y-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
946
947
948
949
950

@EndFunction
*/
void gridInqYunits(int gridID, char *yunits)
{
951
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
953
}

954

Uwe Schulzweida's avatar
Uwe Schulzweida committed
955
956
void gridInqYstdname(int gridID, char *ystdname)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
957
958
959
960
961
962
  if ( ystdname )
    {
      ystdname[0] = 0;
      grid_t *gridptr = grid_to_pointer(gridID);
      if ( gridptr->y.stdname ) strcpy(ystdname, gridptr->y.stdname);
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
963
964
}

965

966
void gridDefProj(int gridID, int projID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
967
{
968
  grid_t *gridptr = grid_to_pointer(gridID);
969
  gridptr->proj = projID;
970
971
972

  if ( gridptr->type == GRID_CURVILINEAR )
    {
973
      grid_t *projptr = grid_to_pointer(projID);
974
975
976
      if ( projptr->x.name[0] ) strcpy(gridptr->x.dimname, projptr->x.name);
      if ( projptr->y.name[0] ) strcpy(gridptr->y.dimname, projptr->y.name);
    }
977
978
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
979

980
981
int gridInqProj(int gridID)
{
982
  grid_t *gridptr = grid_to_pointer(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
983
984
985
  return gridptr->proj;
}

986
987
988

int gridInqProjType(int gridID)
{
989
  grid_t *gridptr = grid_to_pointer(gridID);
990
991
992
993
994
995

  int projtype = gridptr->projtype;

  if ( projtype == -1 )
    {
      char mapping[CDI_MAX_NAME]; mapping[0] = 0;