grid.c 150 KB
Newer Older
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1
#ifdef HAVE_CONFIG_H
2
#include "config.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
3
4
#endif

Thomas Jahns's avatar
Thomas Jahns committed
5
#include <assert.h>
Uwe Schulzweida's avatar
Uwe Schulzweida committed
6
#include <string.h>
7

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

20
int (*proj_lonlat_to_lcc_func)() = NULL;
21
int (*proj_lcc_to_lonlat_func)() = NULL;
22
23
int (*proj_lonlat_to_stere_func)() = NULL;
int (*proj_stere_to_lonlat_func)() = NULL;
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
  /*  0 */  "undefined",
  /*  1 */  "generic",
  /*  2 */  "gaussian",
31
  /*  3 */  "gaussian_reduced",
32
33
34
35
36
  /*  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
  /* 13 */  "characterXY",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
42
43
};

44
45
46
47
48
/* must match table below */
enum xystdname_idx {
  grid_xystdname_grid_latlon,
  grid_xystdname_latlon,
  grid_xystdname_projection,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
49
  grid_xystdname_char,
50
51
52
53
54
55
56
57
};
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
58
59
  [grid_xystdname_char] = { "region",
                            "region" },
60
61
62
};


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);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
68
static void   gridPack        ( void * gridptr, void * buff, int size, int *position, void *context);
Deike Kleberg's avatar
minimal    
Deike Kleberg committed
69
static int    gridTxCode      ( void );
Uwe Schulzweida's avatar
Uwe Schulzweida committed
70

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

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
82

83
grid_t *grid_to_pointer(int gridID)
84
85
86
{
  return (grid_t *)reshGetVal(gridID, &gridOps);
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
87

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

90
91
92
93
94
95
96
static
bool cdiInqAttConvertedToFloat(int gridID, int atttype, const char *attname, int attlen, double *attflt)
{
  bool status = true;

  if ( atttype == CDI_DATATYPE_INT32 )
    {
97
98
      int attint;
      int *pattint = attlen > 1 ? (int*) malloc(attlen*sizeof(int)) : &attint;
99
100
      cdiInqAttInt(gridID, CDI_GLOBAL, attname, attlen, pattint);
      for ( int i = 0; i < attlen; ++i ) attflt[i] = (double)pattint[i];
101
      if (attlen > 1) free(pattint);
102
103
104
105
106
107
108
109
110
111
112
113
114
    }
  else if ( atttype == CDI_DATATYPE_FLT32 || atttype == CDI_DATATYPE_FLT64 )
    {
      cdiInqAttFlt(gridID, CDI_GLOBAL, attname, attlen, attflt);
    }
  else
    {
      status = false;
    }

  return status;
}

115

Deike Kleberg's avatar
Deike Kleberg committed
116
void grid_init(grid_t *gridptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
117
{
118
119
120
  gridptr->self          = CDI_UNDEFID;
  gridptr->type          = CDI_UNDEFID;
  gridptr->proj          = CDI_UNDEFID;
121
  gridptr->projtype      = CDI_UNDEFID;
122
123
  gridptr->mask          = NULL;
  gridptr->mask_gme      = NULL;
124
125
126
127
  gridptr->x.vals        = NULL;
  gridptr->y.vals        = NULL;
  gridptr->x.bounds      = NULL;
  gridptr->y.bounds      = NULL;
128
  gridptr->area          = NULL;
129
130
  gridptr->rowlon        = NULL;
  gridptr->nrowlon       = 0;
131
132
133
134
135
136
#ifndef USE_MPI
  gridptr->x.clength     = 0;
  gridptr->y.clength     = 0;
  gridptr->x.cvals       = NULL;
  gridptr->y.cvals       = NULL;
#endif
137
138
139
140
141
142
  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;
143

144
145
146
147
  gridptr->gme.nd        = 0;
  gridptr->gme.ni        = 0;
  gridptr->gme.ni2       = 0;
  gridptr->gme.ni3       = 0;
148

149
150
151
152
153
  gridptr->trunc         = 0;
  gridptr->nvertex       = 0;
  gridptr->number        = 0;
  gridptr->position      = 0;
  gridptr->reference     = NULL;
154
  gridptr->datatype      = CDI_DATATYPE_FLT64;
155
  gridptr->size          = 0;
156
157
  gridptr->x.size        = 0;
  gridptr->y.size        = 0;
158
  gridptr->np            = 0;
159
160
  gridptr->x.flag        = 0;
  gridptr->y.flag        = 0;
161
  gridptr->isCyclic      = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
162

163
  gridptr->lcomplex      = false;
164
165
166
167
168
169
170
171
172
173
174
  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
175
176
177
  gridptr->vdimname[0]   = 0;
  gridptr->mapname[0]    = 0;
  gridptr->mapping[0]    = 0;
Thomas Jahns's avatar
Thomas Jahns committed
178
  memset(gridptr->uuid, 0, CDI_UUID_SIZE);
179
180
  gridptr->name          = NULL;
  gridptr->vtable        = &cdiGridVtable;
181
  gridptr->atts.nalloc   = MAX_ATTRIBUTES;
182
  gridptr->atts.nelems   = 0;
183
184
185
186
187
188
189
190
191
192
  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
193
194
}

195

196
197
static
void grid_free_components(grid_t *gridptr)
Deike Kleberg's avatar
Deike Kleberg committed
198
{
199
  void *p2free[] = { gridptr->mask, gridptr->mask_gme,
200
                     gridptr->x.vals, gridptr->y.vals,
201
#ifndef USE_MPI
Uwe Schulzweida's avatar
Uwe Schulzweida committed
202
                     gridptr->x.cvals, gridptr->y.cvals,
203
#endif
204
205
206
207
                     gridptr->x.bounds, gridptr->y.bounds,
                     gridptr->rowlon, gridptr->area,
                     gridptr->reference, gridptr->name};

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

212
213
214
void grid_free(grid_t *gridptr)
{
  grid_free_components(gridptr);
Deike Kleberg's avatar
Deike Kleberg committed
215
216
217
  grid_init(gridptr);
}

218
219
static
grid_t *gridNewEntry(cdiResH resH)
220
{
221
  grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t));
222
  grid_init(gridptr);
223

224
  if ( resH == CDI_UNDEFID )
225
226
227
228
229
230
    gridptr->self = reshPut(gridptr, &gridOps);
  else
    {
      gridptr->self = resH;
      reshReplace(resH, gridptr, &gridOps);
    }
231

232
  return gridptr;
233
234
}

235
static
236
void gridInit(void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
237
{
238
  static bool gridInitialized = false;
239
  if ( gridInitialized ) return;
240
  gridInitialized = true;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
241

Uwe Schulzweida's avatar
Uwe Schulzweida committed
242
  const char *env = getenv("GRID_DEBUG");
243
  if ( env ) GRID_Debug = atoi(env);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
244
245
}

246
247
static
void grid_copy_base_scalar_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
248
{
Thomas Jahns's avatar
Thomas Jahns committed
249
250
  memcpy(gridptrDup, gridptrOrig, sizeof(grid_t));
  gridptrDup->self = CDI_UNDEFID;
251
  if ( gridptrOrig->reference )
Thomas Jahns's avatar
Thomas Jahns committed
252
253
254
    gridptrDup->reference = strdupx(gridptrOrig->reference);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
255

256
257
static
grid_t *grid_copy_base(grid_t *gridptrOrig)
Thomas Jahns's avatar
Thomas Jahns committed
258
259
260
261
262
{
  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
263
264
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
265

266
unsigned cdiGridCount(void)
Thomas Jahns's avatar
Thomas Jahns committed
267
{
268
  return reshCountType(&gridOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
269
270
}

271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
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;
}

287
288
static inline
void gridSetName(char *gridstrname, const char *name)
289
{
290
291
  strncpy(gridstrname, name, CDI_MAX_NAME);
  gridstrname[CDI_MAX_NAME - 1] = 0;
292
293
}

294

295
void cdiGridTypeInit(grid_t *gridptr, int gridtype, size_t size)
296
297
298
299
{
  gridptr->type = gridtype;
  gridptr->size = size;

300
301
302
  if      ( gridtype == GRID_LONLAT   ) gridptr->nvertex = 2;
  else if ( gridtype == GRID_GAUSSIAN ) gridptr->nvertex = 2;
  else if ( gridtype == GRID_CURVILINEAR  ) gridptr->nvertex = 4;
303
304
  else if ( gridtype == GRID_UNSTRUCTURED ) gridptr->x.size = size;

305
306
307
308
309
310
  switch (gridtype)
    {
    case GRID_LONLAT:
    case GRID_GAUSSIAN:
    case GRID_GAUSSIAN_REDUCED:
    case GRID_TRAJECTORY:
311
312
313
    case GRID_CURVILINEAR:
    case GRID_UNSTRUCTURED:
    case GRID_GME:
314
315
316
      {
        if ( gridtype == GRID_TRAJECTORY )
          {
317
318
            if ( !gridptr->x.name[0] ) gridSetName(gridptr->x.name, "tlon");
            if ( !gridptr->y.name[0] ) gridSetName(gridptr->y.name, "tlat");
319
320
321
          }
        else
          {
322
323
            if ( !gridptr->x.name[0] ) gridSetName(gridptr->x.name, "lon");
            if ( !gridptr->y.name[0] ) gridSetName(gridptr->y.name, "lat");
324
          }
325

326
327
328
329
330
        if ( !gridptr->x.longname[0] ) gridSetName(gridptr->x.longname, "longitude");
        if ( !gridptr->y.longname[0] ) gridSetName(gridptr->y.longname, "latitude");

        if ( !gridptr->x.units[0] ) gridSetName(gridptr->x.units, "degrees_east");
        if ( !gridptr->y.units[0] ) gridSetName(gridptr->y.units, "degrees_north");
331

332
333
        gridptr->x.stdname = xystdname_tab[grid_xystdname_latlon][0];
        gridptr->y.stdname = xystdname_tab[grid_xystdname_latlon][1];
334

335
336
        break;
      }
337
#ifndef USE_MPI
Uwe Schulzweida's avatar
Uwe Schulzweida committed
338
339
    case GRID_CHARXY:
      {
340
341
342
343
        if ( gridptr->x.cvals ) gridptr->x.stdname = xystdname_tab[grid_xystdname_char][0];
        if ( gridptr->y.cvals ) gridptr->y.stdname = xystdname_tab[grid_xystdname_char][0];

        break;
344
345
      }
#endif
346
    case GRID_GENERIC:
347
    case GRID_PROJECTION:
348
      {
349
350
        if ( gridptr->x.name[0] == 0 ) gridSetName(gridptr->x.name, "x");
        if ( gridptr->y.name[0] == 0 ) gridSetName(gridptr->y.name, "y");
351
352
353
        if ( gridtype == GRID_PROJECTION )
          {
            gridSetName(gridptr->mapname, "Projection");
354

355
356
            gridptr->x.stdname = xystdname_tab[grid_xystdname_projection][0];
            gridptr->y.stdname = xystdname_tab[grid_xystdname_projection][1];
357
358
359

            if ( !gridptr->x.units[0] ) gridSetName(gridptr->x.units, "m");
            if ( !gridptr->y.units[0] ) gridSetName(gridptr->y.units, "m");
360
          }
361
362
363
364
365
366
        break;
      }
    }
}


367
// used also in CDO
368
void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *restrict xvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
370
  if (fabs(xinc) <= 0 && xsize > 1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
371
372
    {
      if ( xfirst >= xlast )
Thomas Jahns's avatar
Thomas Jahns committed
373
374
375
376
        {
          while ( xfirst >= xlast ) xlast += 360;
          xinc = (xlast-xfirst)/(xsize);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
377
      else
Thomas Jahns's avatar
Thomas Jahns committed
378
379
380
        {
          xinc = (xlast-xfirst)/(xsize-1);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
381
382
    }

383
  for ( int i = 0; i < xsize; ++i )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
384
385
386
    xvals[i] = xfirst + i*xinc;
}

387
static
388
void calc_gaussgrid(double *restrict yvals, size_t ysize, double yfirst, double ylast)
389
{
390
  double *restrict yw = (double *) Malloc(ysize * sizeof(double));
391
  gaussianLatitudes(yvals, yw, ysize);
392
  Free(yw);
393
  for (size_t i = 0; i < ysize; i++ )
394
395
396
397
    yvals[i] = asin(yvals[i])/M_PI*180.0;

  if ( yfirst < ylast && yfirst > -90.0 && ylast < 90.0 )
    {
398
      const size_t yhsize = ysize/2;
399
      for (size_t i = 0; i < yhsize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
400
        {
401
          const double ytmp = yvals[i];
Thomas Jahns's avatar
Thomas Jahns committed
402
403
404
          yvals[i] = yvals[ysize-i-1];
          yvals[ysize-i-1] = ytmp;
        }
405
406
407
    }
}

408
409
static
void gridGenYvalsGaussian(int ysize, double yfirst, double ylast, double *restrict yvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
410
{
411
  const double deleps = 0.002;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
412

413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
  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 )
      {
        double *ytmp = NULL;
        int nstart;
        bool lfound = false;
        int ny = (int) (180./(fabs(ylast-yfirst)/(ysize-1)) + 0.5);
        ny -= ny%2;
        if ( ny > ysize && ny < 4096 )
          {
            ytmp = (double *) Malloc((size_t)ny * sizeof (double));
            calc_gaussgrid(ytmp, ny, yfirst, ylast);
            {
              int i;
              for ( i = 0; i < (ny-ysize); i++ )
                if ( fabs(ytmp[i] - yfirst) < deleps ) break;
              nstart = i;
            }

            lfound = (nstart+ysize-1) < ny && fabs(ytmp[nstart+ysize-1] - ylast) < deleps;
            if ( lfound )
              {
                for (int i = 0; i < ysize; i++) yvals[i] = ytmp[i+nstart];
              }
          }

        if ( !lfound )
          {
            Warning("Cannot calculate gaussian latitudes for lat1 = %g latn = %g!", yfirst, ylast);
            for (int i = 0; i < ysize; i++ ) yvals[i] = 0;
            yvals[0] = yfirst;
            yvals[ysize-1] = ylast;
          }

        if ( ytmp ) Free(ytmp);
      }
}

static
void gridGenYvalsRegular(int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
{
  if (fabs(yinc) <= 0 && ysize > 1)
    {
      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;
            }
        }
    }

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

  for (int i = 0; i < ysize; i++ )
    yvals[i] = yfirst + i*yinc;
}

// used also in CDO
void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
489
490
  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
    {
      if ( ysize > 2 )
Deike Kleberg's avatar
Deike Kleberg committed
491
	{
492
          gridGenYvalsGaussian(ysize, yfirst, ylast, yvals);
Deike Kleberg's avatar
Deike Kleberg committed
493
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494
      else
Thomas Jahns's avatar
Thomas Jahns committed
495
496
497
498
        {
          yvals[0] = yfirst;
          yvals[ysize-1] = ylast;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
500
501
502
    }
  /*     else if ( gridtype == GRID_LONLAT || gridtype == GRID_GENERIC ) */
  else
    {
503
      gridGenYvalsRegular(ysize, yfirst, ylast, yinc, yvals);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
504
    }
505
   /*
Uwe Schulzweida's avatar
Uwe Schulzweida committed
506
    else
507
    Error("unable to calculate values for %s grid!", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509
510
511
  */
}

/*
512
@Function  gridCreate
513
@Title     Create a horizontal Grid
Uwe Schulzweida's avatar
Uwe Schulzweida committed
514

515
@Prototype int gridCreate(int gridtype, size_t size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
516
517
@Parameter
    @Item  gridtype  The type of the grid, one of the set of predefined CDI grid types.
518
                     The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
519
                     @func{GRID_LONLAT}, @func{GRID_PROJECTION}, @func{GRID_SPECTRAL},
520
                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
521
522
523
    @Item  size      Number of gridpoints.

@Description
524
The function @func{gridCreate} creates a horizontal Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
525
526

@Result
527
@func{gridCreate} returns an identifier to the Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528
529

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

@Source
Uwe Schulzweida's avatar
Uwe Schulzweida committed
533
534
#include "cdi.h"
   ...
535
536
#define  nlon  12
#define  nlat   6
Uwe Schulzweida's avatar
Uwe Schulzweida committed
537
   ...
538
539
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
540
541
int gridID;
   ...
542
543
544
gridID = gridCreate(GRID_LONLAT, nlon*nlat);
gridDefXsize(gridID, nlon);
gridDefYsize(gridID, nlat);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
545
546
547
548
gridDefXvals(gridID, lons);
gridDefYvals(gridID, lats);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
549
550
@EndFunction
*/
551
int gridCreate(int gridtype, size_t size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
552
{
553
  if ( CDI_Debug ) Message("gridtype=%s  size=%zu", gridNamePtr(gridtype), size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
554

555
  xassert(size);
556
  gridInit();
557

Uwe Schulzweida's avatar
Uwe Schulzweida committed
558
  grid_t *gridptr = gridNewEntry(CDI_UNDEFID);
559
  if ( ! gridptr ) Error("No memory");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
560

561
  const int gridID = gridptr->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
562

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

565
  cdiGridTypeInit(gridptr, gridtype, size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
566

Uwe Schulzweida's avatar
Uwe Schulzweida committed
567
  return gridID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
568
569
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
571
static
void gridDestroyKernel( grid_t * gridptr )
572
{
Deike Kleberg's avatar
Deike Kleberg committed
573
  xassert ( gridptr );
574

575
  const int id = gridptr->self;
576

577
  grid_free_components(gridptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
578
  Free( gridptr );
579

580
  reshRemove( id, &gridOps );
581
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
582

583
584
585
586
587
588
/*
@Function  gridDestroy
@Title     Destroy a horizontal Grid

@Prototype void gridDestroy(int gridID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
589
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
590
591
592
593
594

@EndFunction
*/
void gridDestroy(int gridID)
{
595
  grid_t *gridptr = grid_to_pointer(gridID);
596
  gridptr->vtable->destroy(gridptr);
597
598
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
599
600
static
void gridDestroyP(void * gridptr)
601
{
602
  ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
603
604
605
}


606
const char *gridNamePtr(int gridtype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
607
{
608
  const int size = (int) (sizeof(Grids)/sizeof(Grids[0]));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
609

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
  return name;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
613
614
615
616
617
618
619
620
}


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

621
static
622
void *grid_key_to_ptr(grid_t *gridptr, int key)
623
{
624
  void *keyptr = NULL;
625
626
627

  switch (key)
    {
628
629
630
631
632
633
634
635
636
    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;
637
638
    case CDI_KEY_MAPPING:    keyptr = (void*)gridptr->mapname; break;
    case CDI_KEY_MAPNAME:    keyptr = (void*)gridptr->mapping; break;
639
640
    }

641
  return keyptr;
642
643
}

644
/*
645
@Function  cdiGridDefKeyStr
646
647
@Title     Define a CDI grid string value from a key

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

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

@EndFunction
*/
663
int cdiGridDefKeyStr(int gridID, int key, int size, const char *mesg)
664
{
665
  if ( size < 1 || mesg == NULL || *mesg == 0 ) return -1;
666

667
  grid_t *gridptr = grid_to_pointer(gridID);
668

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

676
  gridSetString(keyptr, mesg, (size_t)size);
677
678
679
680
681
682
  gridMark4Update(gridID);

  return 0;
}

/*
683
@Function  cdiGridInqKeyStr
684
685
@Title     Get a CDI grid string value from a key

686
@Prototype int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
687
688
689
690
691
692
693
694
695
696
@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
697
The function @func{cdiGridInqKeyStr} return a CDI grid string value from a key.
698
699

@Result
700
@func{cdiGridInqKeyStr} returns 0 if OK and integer value on error.
701
702
703

@EndFunction
*/
704
int cdiGridInqKeyStr(int gridID, int key, int size, char *mesg)
705
{
706
  if ( size < 1 || mesg == NULL ) return -1;
707

708
  grid_t *gridptr = grid_to_pointer(gridID);
709
710
  const char *keyptr = (const char*)grid_key_to_ptr(gridptr, key);
  if ( keyptr == NULL)
711
712
713
714
715
    {
      Warning("CDI grid string key %d not supported!", key);
      return -1;
    }

716
  gridGetString(mesg, keyptr, (size_t)size);
717
718
719
720

  return 0;
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
721
722
723
724
725
726
/*
@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
727
728
    @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
729
730

@Description
731
The function @func{gridDefXname} defines the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
732
733
734

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
735
void gridDefXname(int gridID, const char *xname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
736
{
737
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
738
739
740
741
742
743
744
745
}

/*
@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
746
747
    @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
748
749

@Description
750
The function @func{gridDefXlongname} defines the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
751
752
753

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
void gridDefXlongname(int gridID, const char *xlongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
755
{
756
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
758
759
760
761
762
763
764
}

/*
@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
765
766
    @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
767
768

@Description
769
The function @func{gridDefXunits} defines the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
770
771
772

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773
void gridDefXunits(int gridID, const char *xunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
774
{
775
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_XUNITS, CDI_MAX_NAME, xunits);
776
777
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
778
779
780
781
782
783
/*
@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
784
785
    @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
786
787

@Description
788
The function @func{gridDefYname} defines the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
790
791

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

/*
@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
803
804
    @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
805
806

@Description
807
The function @func{gridDefYlongname} defines the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
808
809
810

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
811
void gridDefYlongname(int gridID, const char *ylongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
{
813
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
814
815
816
817
818
819
820
821
}

/*
@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
822
823
    @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
824
825

@Description
826
The function @func{gridDefYunits} defines the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
827
828
829

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
830
void gridDefYunits(int gridID, const char *yunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831
{
832
  (void)cdiGridDefKeyStr(gridID, CDI_KEY_YUNITS, CDI_MAX_NAME, yunits);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
833
834
835
836
837
838
}

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

Deike Kleberg's avatar
Deike Kleberg committed
839
@Prototype void gridInqXname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
840
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
841
842
    @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
843
                    returned string. The maximum possible length, in characters, of
844
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846

@Description
847
The function @func{gridInqXname} returns the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
849

@Result
850
@func{gridInqXname} returns the name of the X-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
851
852
853
854
855

@EndFunction
*/
void gridInqXname(int gridID, char *xname)
{
856
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XNAME, CDI_MAX_NAME, xname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
857
858
859
860
861
862
}

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

Deike Kleberg's avatar
Deike Kleberg committed
863
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
864
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
865
866
    @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
867
                    returned string. The maximum possible length, in characters, of
868
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
869
870

@Description
871
The function @func{gridInqXlongname} returns the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
872
873

@Result
874
@func{gridInqXlongname} returns the longname of the X-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
875
876
877
878
879

@EndFunction
*/
void gridInqXlongname(int gridID, char *xlongname)
{
880
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_XLONGNAME, CDI_MAX_NAME, xlongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
881
882
883
884
885
886
}

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

Deike Kleberg's avatar
Deike Kleberg committed
887
@Prototype void gridInqXunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
888
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
889
890
    @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
891
                    returned string. The maximum possible length, in characters, of
892
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
893
894

@Description
895
The function @func{gridInqXunits} returns the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
896
897

@Result
898
@func{gridInqXunits} returns the units of the X-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
899
900
901
902
903

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


void gridInqXstdname(int gridID, char *xstdname)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
910
911
912
913
914
915
  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
916
917
918
919
920
921
}

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

Deike Kleberg's avatar
Deike Kleberg committed
922
@Prototype void gridInqYname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
923
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
924
925
    @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
926
                    returned string. The maximum possible length, in characters, of
927
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
928
929

@Description
930
The function @func{gridInqYname} returns the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
931
932

@Result
933
@func{gridInqYname} returns the name of the Y-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
934
935
936
937
938

@EndFunction
*/
void gridInqYname(int gridID, char *yname)
{
939
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YNAME, CDI_MAX_NAME, yname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
940
941
942
943
944
945
}

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

946
@Prototype void gridInqYlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
947
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
948
949
    @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
950
                    returned string. The maximum possible length, in characters, of
951
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
953

@Description
954
The function @func{gridInqYlongname} returns the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
955
956

@Result
957
@func{gridInqYlongname} returns the longname of the Y-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
958
959
960
961
962

@EndFunction
*/
void gridInqYlongname(int gridID, char *ylongname)
{
963
  (void)cdiGridInqKeyStr(gridID, CDI_KEY_YLONGNAME, CDI_MAX_NAME, ylongname);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
964
965
966
967
968
969
}

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

Deike Kleberg's avatar
Deike Kleberg committed
970
@Prototype void gridInqYunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
971
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
972
973
    @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
974
                    returned string. The maximum possible length, in characters, of
975
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
976
977

@Description
978
The function @func{gridInqYunits} returns the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
979
980

@Result
981
@func{gridInqYunits} returns the units of the Y-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
982
983
984
985
986

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

990

Uwe Schulzweida's avatar
Uwe Schulzweida committed
991
992
void gridInqYstdname(int gridID, char *ystdname)
{
Uwe Schulzweida's avatar
Uwe Schulzweida committed
993
994
995
996
997
998
  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
999
1000
}

1001

1002
void gridDefProj(int gridID, int projID)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
1003
{
1004
  grid_t *gridptr = grid_to_pointer(gridID);