grid.c 138 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
23
24
#include "vlist.h"

#undef  UNDEFID
#define UNDEFID -1
Uwe Schulzweida's avatar
Uwe Schulzweida committed
25

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

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* 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
63

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

72
static const resOps gridOps = {
73
74
75
76
77
78
  gridCompareP,
  gridDestroyP,
  gridPrintP,
  gridGetPackSize,
  gridPack,
  gridTxCode
79
};
Uwe Schulzweida's avatar
Uwe Schulzweida committed
80

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

83
84
85
86
grid_t *gridID2Ptr(int gridID)
{
  return (grid_t *)reshGetVal(gridID, &gridOps);
}
87
#define gridID2Ptr(gridID) (grid_t *)reshGetVal(gridID, &gridOps)
88
#define gridMark4Update(gridID) reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
89

90

Deike Kleberg's avatar
Deike Kleberg committed
91
void grid_init(grid_t *gridptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
92
{
93
94
95
  gridptr->self          = CDI_UNDEFID;
  gridptr->type          = CDI_UNDEFID;
  gridptr->proj          = CDI_UNDEFID;
96
  gridptr->projtype      = CDI_UNDEFID;
97
98
  gridptr->mask          = NULL;
  gridptr->mask_gme      = NULL;
99
100
101
102
  gridptr->x.vals        = NULL;
  gridptr->y.vals        = NULL;
  gridptr->x.bounds      = NULL;
  gridptr->y.bounds      = NULL;
103
  gridptr->area          = NULL;
104
105
  gridptr->rowlon        = NULL;
  gridptr->nrowlon       = 0;
106

107
108
109
110
111
112
  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;
113

114
115
116
117
118
119
120
121
122
123
  gridptr->lcc.originLon = 0.0;
  gridptr->lcc.originLat = 0.0;
  gridptr->lcc.lonParY   = 0.0;
  gridptr->lcc.lat1      = 0.0;
  gridptr->lcc.lat2      = 0.0;
  gridptr->lcc.xinc      = 0.0;
  gridptr->lcc.yinc      = 0.0;
  gridptr->lcc.projflag  = 0;
  gridptr->lcc.scanflag  = 0;
  gridptr->lcc.defined   = FALSE;
124
125
126
127
128
129
  gridptr->lcc2.lon_0    = 0.0;
  gridptr->lcc2.lat_0    = 0.0;
  gridptr->lcc2.lat_1    = 0.0;
  gridptr->lcc2.lat_2    = 0.0;
  gridptr->lcc2.a        = 0.0;
  gridptr->lcc2.defined  = FALSE;
130

131
132
133
134
  gridptr->laea.lon_0    = 0.0;
  gridptr->laea.lat_0    = 0.0;
  gridptr->laea.a        = 0.0;
  gridptr->laea.defined  = FALSE;
135

136
137
138
139
  gridptr->gme.nd        = 0;
  gridptr->gme.ni        = 0;
  gridptr->gme.ni2       = 0;
  gridptr->gme.ni3       = 0;
140

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

155
  gridptr->lcomplex      = false;
156
157
158
159
160
161
162
163
164
165
166
  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
167
168
169
  gridptr->vdimname[0]   = 0;
  gridptr->mapname[0]    = 0;
  gridptr->mapping[0]    = 0;
Thomas Jahns's avatar
Thomas Jahns committed
170
  memset(gridptr->uuid, 0, CDI_UUID_SIZE);
171
172
  gridptr->name          = NULL;
  gridptr->vtable        = &cdiGridVtable;
173
  gridptr->atts.nalloc   = MAX_ATTRIBUTES;
174
  gridptr->atts.nelems   = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
175
176
}

177

178
179
static void
grid_free_components(grid_t *gridptr)
Deike Kleberg's avatar
Deike Kleberg committed
180
{
181
  void *p2free[] = { gridptr->mask, gridptr->mask_gme,
182
183
184
185
186
187
188
                     gridptr->x.vals, gridptr->y.vals,
                     gridptr->x.bounds, gridptr->y.bounds,
                     gridptr->rowlon, gridptr->area,
                     gridptr->reference, gridptr->name};

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

191
192
193
void grid_free(grid_t *gridptr)
{
  grid_free_components(gridptr);
Deike Kleberg's avatar
Deike Kleberg committed
194
195
196
  grid_init(gridptr);
}

197
198
static
grid_t *gridNewEntry(cdiResH resH)
199
{
200
  grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t));
201
  grid_init(gridptr);
202

203
204
205
206
207
208
209
  if (resH == CDI_UNDEFID)
    gridptr->self = reshPut(gridptr, &gridOps);
  else
    {
      gridptr->self = resH;
      reshReplace(resH, gridptr, &gridOps);
    }
210

211
  return gridptr;
212
213
}

214
static
215
void gridInit(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
216
{
217
  static int gridInitialized = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
218

219
  if ( gridInitialized ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220

Thomas Jahns's avatar
Thomas Jahns committed
221
  gridInitialized = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
222

Uwe Schulzweida's avatar
Uwe Schulzweida committed
223
  const char *env = getenv("GRID_DEBUG");
224
  if ( env ) GRID_Debug = atoi(env);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
225
226
}

Thomas Jahns's avatar
Thomas Jahns committed
227
228
static void
grid_copy_base_scalar_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
229
{
Thomas Jahns's avatar
Thomas Jahns committed
230
231
232
233
234
235
  memcpy(gridptrDup, gridptrOrig, sizeof(grid_t));
  gridptrDup->self = CDI_UNDEFID;
  if (gridptrOrig->reference)
    gridptrDup->reference = strdupx(gridptrOrig->reference);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
236

Thomas Jahns's avatar
Thomas Jahns committed
237
238
239
240
241
242
243
static grid_t *
grid_copy_base(grid_t *gridptrOrig)
{
  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
244
245
}

246
unsigned cdiGridCount(void)
Thomas Jahns's avatar
Thomas Jahns committed
247
{
248
  return reshCountType(&gridOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
249
250
}

251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
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;
}

267
268
static inline
void gridSetName(char *gridstrname, const char *name)
269
{
270
271
  strncpy(gridstrname, name, CDI_MAX_NAME);
  gridstrname[CDI_MAX_NAME - 1] = 0;
272
273
}

274
275

void cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
276
277
278
279
{
  gridptr->type = gridtype;
  gridptr->size = size;

280
281
282
  if      ( gridtype == GRID_CURVILINEAR  ) gridptr->nvertex = 4;
  else if ( gridtype == GRID_UNSTRUCTURED ) gridptr->x.size = size;

283
284
285
286
287
288
  switch (gridtype)
    {
    case GRID_LONLAT:
    case GRID_GAUSSIAN:
    case GRID_GAUSSIAN_REDUCED:
    case GRID_TRAJECTORY:
289
290
291
    case GRID_CURVILINEAR:
    case GRID_UNSTRUCTURED:
    case GRID_GME:
292
293
294
      {
        if ( gridtype == GRID_TRAJECTORY )
          {
295
296
            if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "tlon");
            if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "tlat");
297
298
299
          }
        else
          {
300
301
            if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "lon");
            if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "lat");
302
          }
303

304
305
        gridSetName(gridptr->x.longname, "longitude");
        gridSetName(gridptr->y.longname, "latitude");
306

307
308
        gridptr->x.stdname = xystdname_tab[grid_xystdname_latlon][0];
        gridptr->y.stdname = xystdname_tab[grid_xystdname_latlon][1];
309
310
        gridSetName(gridptr->x.units, "degrees_east");
        gridSetName(gridptr->y.units, "degrees_north");
311

312
313
314
        break;
      }
    case GRID_GENERIC:
315
    case GRID_PROJECTION:
316
317
    case GRID_LCC2:
    case GRID_LAEA:
318
      {
319
320
        if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "x");
        if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "y");
321
322
323
324
        if ( gridtype == GRID_PROJECTION )
          {
            gridSetName(gridptr->mapname, "Projection");
          }
325
326
327
328
329
330
331
        if ( gridtype != GRID_GENERIC )
          {
            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");
          }
332
333
334
335
336
337
        break;
      }
    }
}


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

354
  for ( int i = 0; i < xsize; ++i )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
355
356
357
    xvals[i] = xfirst + i*xinc;
}

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

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

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

  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
    {
      if ( ysize > 2 )
Deike Kleberg's avatar
Deike Kleberg committed
387
388
389
390
391
392
	{
	  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 )
	      {
393
		double *restrict ytmp = NULL;
Deike Kleberg's avatar
Deike Kleberg committed
394
		int nstart, lfound = 0;
395
		int ny = (int) (180./(fabs(ylast-yfirst)/(ysize-1)) + 0.5);
Deike Kleberg's avatar
Deike Kleberg committed
396
397
398
		ny -= ny%2;
		if ( ny > ysize && ny < 4096 )
		  {
399
		    ytmp = (double *) Malloc((size_t)ny * sizeof (double));
Deike Kleberg's avatar
Deike Kleberg committed
400
		    calc_gaussgrid(ytmp, ny, yfirst, ylast);
401
402
403
404
405
406
                    {
                      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
407

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

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

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

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

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

/*
471
@Function  gridCreate
472
@Title     Create a horizontal Grid
Uwe Schulzweida's avatar
Uwe Schulzweida committed
473

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

@Description
483
The function @func{gridCreate} creates a horizontal Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
485

@Result
486
@func{gridCreate} returns an identifier to the Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
487
488

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

@Source
Uwe Schulzweida's avatar
Uwe Schulzweida committed
492
493
#include "cdi.h"
   ...
494
495
#define  nlon  12
#define  nlat   6
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
   ...
497
498
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
499
500
int gridID;
   ...
501
502
503
gridID = gridCreate(GRID_LONLAT, nlon*nlat);
gridDefXsize(gridID, nlon);
gridDefYsize(gridID, nlat);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504
505
506
507
gridDefXvals(gridID, lons);
gridDefYvals(gridID, lats);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
@EndFunction
*/
510
int gridCreate(int gridtype, int size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
511
{
512
  if ( CDI_Debug ) Message("gridtype=%s  size=%d", gridNamePtr(gridtype), size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513

514
  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
515

516
  gridInit();
517

Uwe Schulzweida's avatar
Uwe Schulzweida committed
518
  grid_t *gridptr = gridNewEntry(CDI_UNDEFID);
519
  if ( ! gridptr ) Error("No memory");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
520

Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
  int gridID = gridptr->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
522

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

525
  cdiGridTypeInit(gridptr, gridtype, size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
526

Uwe Schulzweida's avatar
Uwe Schulzweida committed
527
  return gridID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528
529
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
530
531
static
void gridDestroyKernel( grid_t * gridptr )
532
{
Deike Kleberg's avatar
Deike Kleberg committed
533
  xassert ( gridptr );
534

535
  int id = gridptr->self;
536

537
  grid_free_components(gridptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
538
  Free( gridptr );
539

540
  reshRemove ( id, &gridOps );
541
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
542

543
544
545
546
547
548
/*
@Function  gridDestroy
@Title     Destroy a horizontal Grid

@Prototype void gridDestroy(int gridID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
549
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
550
551
552
553
554

@EndFunction
*/
void gridDestroy(int gridID)
{
555
  grid_t *gridptr = gridID2Ptr(gridID);
556
  gridptr->vtable->destroy(gridptr);
557
558
}

559

560
void gridDestroyP ( void * gridptr )
561
{
562
  ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
563
564
565
}


566
const char *gridNamePtr(int gridtype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
{
568
  int size = (int) (sizeof(Grids)/sizeof(Grids[0]));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
569

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
572
  return name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
573
574
575
576
577
578
579
580
}


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

581
static
582
void *grid_key_to_ptr(grid_t *gridptr, int key)
583
{
584
  void *keyptr = NULL;
585
586
587

  switch (key)
    {
588
589
590
591
592
593
594
595
596
    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;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
597
    case CDI_KEY_MAPNAME:    keyptr = (void*)gridptr->mapname; break;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
598
    case CDI_KEY_MAPPING:    keyptr = (void*)gridptr->mapping; break;
599
600
    }

601
  return keyptr;
602
603
}

604
/*
605
@Function  cdiGridDefKeyStr
606
607
@Title     Define a CDI grid string value from a key

608
@Prototype int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg)
609
610
611
612
613
614
615
@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
616
The function @func{cdiGridDefKeyStr} defines a CDI grid string value from a key.
617
618

@Result
619
@func{cdiGridDefKeyStr} returns 0 if OK and integer value on error.
620
621
622

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

  grid_t *gridptr = gridID2Ptr(gridID);

629
  char *gridstring = (char*)grid_key_to_ptr(gridptr, key);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
630
  if ( gridstring == NULL )
631
632
633
634
635
    {
      Warning("CDI grid string key %d not supported!", key);
      return -1;
    }

636
  gridSetString(gridstring, mesg, (size_t)size);
637
638
639
640
641
642
  gridMark4Update(gridID);

  return 0;
}

/*
643
@Function  cdiGridInqKeyStr
644
645
@Title     Get a CDI grid string value from a key

646
@Prototype int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
647
648
649
650
651
652
653
654
655
656
@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
657
The function @func{cdiGridInqKeyStr} return a CDI grid string value from a key.
658
659

@Result
660
@func{cdiGridInqKeyStr} returns 0 if OK and integer value on error.
661
662
663

@EndFunction
*/
664
int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
665
{
666
  if ( size < 1 || mesg == NULL ) return -1;
667
668

  grid_t *gridptr = gridID2Ptr(gridID);
669
  const char *gridstring = (const char*)grid_key_to_ptr(gridptr, key);
670
  if ( gridstring == NULL)
671
672
673
674
675
    {
      Warning("CDI grid string key %d not supported!", key);
      return -1;
    }

676
  gridGetString(mesg, gridstring, (size_t)size);
677
678
679
680

  return 0;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
681
682
683
684
685
686
/*
@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
687
688
    @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
689
690

@Description
691
The function @func{gridDefXname} defines the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
692
693
694

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

/*
@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
706
707
    @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
708
709

@Description
710
The function @func{gridDefXlongname} defines the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
711
712
713

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

/*
@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
725
726
    @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
727
728

@Description
729
The function @func{gridDefXunits} defines the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730
731
732

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
733
void gridDefXunits(int gridID, const char *xunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
{
735
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
736
737
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
739
740
741
742
743
/*
@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
744
745
    @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
746
747

@Description
748
The function @func{gridDefYname} defines the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
749
750
751

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

/*
@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
763
764
    @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
765
766

@Description
767
The function @func{gridDefYlongname} defines the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
768
769
770

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

/*
@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
782
783
    @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
784
785

@Description
786
The function @func{gridDefYunits} defines the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
787
788
789

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
790
void gridDefYunits(int gridID, const char *yunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
791
{
792
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
793
794
795
796
797
798
}

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

Deike Kleberg's avatar
Deike Kleberg committed
799
@Prototype void gridInqXname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
800
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
801
802
    @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
803
                    returned string. The maximum possible length, in characters, of
804
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
806

@Description
807
The function @func{gridInqXname} returns the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
808
809

@Result
810
@func{gridInqXname} returns the name of the X-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
811
812
813
814
815

@EndFunction
*/
void gridInqXname(int gridID, char *xname)
{
816
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
817
818
819
820
821
822
}

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

Deike Kleberg's avatar
Deike Kleberg committed
823
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
824
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
825
826
    @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
827
                    returned string. The maximum possible length, in characters, of
828
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
829
830

@Description
831
The function @func{gridInqXlongname} returns the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
832
833

@Result
834
@func{gridInqXlongname} returns the longname of the X-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
835
836
837
838
839

@EndFunction
*/
void gridInqXlongname(int gridID, char *xlongname)
{
840
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
841
842
843
844
845
846
}

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

Deike Kleberg's avatar
Deike Kleberg committed
847
@Prototype void gridInqXunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
849
850
    @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
851
                    returned string. The maximum possible length, in characters, of
852
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
854

@Description
855
The function @func{gridInqXunits} returns the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
856
857

@Result
858
@func{gridInqXunits} returns the units of the X-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
859
860
861
862
863

@EndFunction
*/
void gridInqXunits(int gridID, char *xunits)
{
864
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
865
866
867
868
869
}


void gridInqXstdname(int gridID, char *xstdname)
{
870
  grid_t *gridptr = gridID2Ptr(gridID);
871
872
  if ( gridptr->x.stdname )
    strcpy(xstdname, gridptr->x.stdname);
873
874
  else
    xstdname[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
875
876
877
878
879
880
}

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

Deike Kleberg's avatar
Deike Kleberg committed
881
@Prototype void gridInqYname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
    @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
885
                    returned string. The maximum possible length, in characters, of
886
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
888

@Description
889
The function @func{gridInqYname} returns the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
891

@Result
892
@func{gridInqYname} returns the name of the Y-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
893
894
895
896
897

@EndFunction
*/
void gridInqYname(int gridID, char *yname)
{
898
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
899
900
901
902
903
904
}

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

Deike Kleberg's avatar
Deike Kleberg committed
905
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
906
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
908
    @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
909
                    returned string. The maximum possible length, in characters, of
910
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
911
912

@Description
913
The function @func{gridInqYlongname} returns the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
914
915

@Result
916
@func{gridInqYlongname} returns the longname of the Y-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
917
918
919
920
921

@EndFunction
*/
void gridInqYlongname(int gridID, char *ylongname)
{
922
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
923
924
925
926
927
928
}

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

Deike Kleberg's avatar
Deike Kleberg committed
929
@Prototype void gridInqYunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
930
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
932
    @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
933
                    returned string. The maximum possible length, in characters, of
934
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
935
936

@Description
937
The function @func{gridInqYunits} returns the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
938
939

@Result
940
@func{gridInqYunits} returns the units of the Y-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
941
942
943
944
945

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

949

Uwe Schulzweida's avatar
Uwe Schulzweida committed
950
951
void gridInqYstdname(int gridID, char *ystdname)
{
952
  grid_t *gridptr = gridID2Ptr(gridID);
953
954
  if ( gridptr->y.stdname )
    strcpy(ystdname, gridptr->y.stdname);
955
956
  else
    ystdname[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
957
958
}

959

960
void gridDefProj(int gridID, int projID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
961
962
{
  grid_t *gridptr = gridID2Ptr(gridID);
963
  gridptr->proj = projID;
964
965
966
967
968
969
970

  if ( gridptr->type == GRID_CURVILINEAR )
    {
      grid_t *projptr = gridID2Ptr(projID);
      if ( projptr->x.name[0] ) strcpy(gridptr->x.dimname, projptr->x.name);
      if ( projptr->y.name[0] ) strcpy(gridptr->y.dimname, projptr->y.name);
    }
971
972
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
973

974
975
976
int gridInqProj(int gridID)
{
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
977
978
979
  return gridptr->proj;
}

980
981
982
983
984
985
986
987
988
989
990
991
992

int gridInqProjType(int gridID)
{
  grid_t *gridptr = gridID2Ptr(gridID);

  int projtype = gridptr->projtype;

  if ( projtype == -1 )
    {
      char mapping[CDI_MAX_NAME]; mapping[0] = 0;
      cdiGridInqKeyStr(gridID, CDI_KEY_MAPPING, CDI_MAX_NAME, mapping);
      if ( mapping[0] )
        {
993
994
995
996
997
          if      ( strcmp(mapping, "rotated_latitude_longitude") == 0 )   projtype = CDI_PROJ_RLL;
          else if ( strcmp(mapping, "lambert_azimuthal_equal_area") == 0 ) projtype = CDI_PROJ_LAEA;
          else if ( strcmp(mapping, "lambert_conformal_conic") == 0 )      projtype = CDI_PROJ_LCC;
          else if ( strcmp(mapping, "sinusoidal") == 0 )                   projtype = CDI_PROJ_SINU;

998
999
1000
1001
1002
1003
1004
          gridptr->projtype = projtype;
        }
    }

  return projtype;
}

1005
1006
1007
1008