grid.c 131 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
43
  /* 12 */  "lcc2",
  /* 13 */  "laea",
  /* 14 */  "sinusoidal",
44
  /* 15 */  "projection",
Uwe Schulzweida's avatar
Uwe Schulzweida committed
45
46
};

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

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

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

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

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

91

Deike Kleberg's avatar
Deike Kleberg committed
92
void grid_init(grid_t *gridptr)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
93
{
94
  gridptr->self         = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
95
  gridptr->type         = CDI_UNDEFID;
Deike Kleberg's avatar
Deike Kleberg committed
96
  gridptr->proj         = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
97
  gridptr->mask         = NULL;
98
  gridptr->mask_gme     = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
99
100
101
102
103
104
105
  gridptr->xvals        = NULL;
  gridptr->yvals        = NULL;
  gridptr->area         = NULL;
  gridptr->xbounds      = NULL;
  gridptr->ybounds      = NULL;
  gridptr->rowlon       = NULL;
  gridptr->nrowlon      = 0;
106
107
  gridptr->xfirst       = 0.0;
  gridptr->xlast        = 0.0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
108
  gridptr->xinc         = 0.0;
109
110
  gridptr->yfirst       = 0.0;
  gridptr->ylast        = 0.0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
111
  gridptr->yinc         = 0.0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
112
113
114
115
116
117
118
  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;
119
120
  gridptr->lcc_projflag = 0;
  gridptr->lcc_scanflag = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
121
  gridptr->lcc_defined  = FALSE;
122
123
124
125
126
127
  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;
128
129
130
131
  gridptr->laea_lon_0   = 0.0;
  gridptr->laea_lat_0   = 0.0;
  gridptr->laea_a       = 0.0;
  gridptr->laea_defined = FALSE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
132
133
134
135
136
137
  gridptr->trunc        = 0;
  gridptr->nvertex      = 0;
  gridptr->nd           = 0;
  gridptr->ni           = 0;
  gridptr->ni2          = 0;
  gridptr->ni3          = 0;
138
139
140
  gridptr->number       = 0;
  gridptr->position     = 0;
  gridptr->reference    = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
141
142
143
144
  gridptr->prec         = 0;
  gridptr->size         = 0;
  gridptr->xsize        = 0;
  gridptr->ysize        = 0;
145
  gridptr->np           = 0;
146
147
  gridptr->xdef         = 0;
  gridptr->ydef         = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
148
  gridptr->isCyclic     = CDI_UNDEFID;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
149
150
151
152
  gridptr->isRotated    = FALSE;
  gridptr->xpole        = 0.0;
  gridptr->ypole        = 0.0;
  gridptr->angle        = 0.0;
153
  gridptr->lcomplex     = 0;
154
  gridptr->hasdims      = TRUE;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
155
156
157
158
159
160
  gridptr->xname[0]     = 0;
  gridptr->yname[0]     = 0;
  gridptr->xlongname[0] = 0;
  gridptr->ylongname[0] = 0;
  gridptr->xunits[0]    = 0;
  gridptr->yunits[0]    = 0;
161
162
  gridptr->xstdname  = NULL;
  gridptr->ystdname  = NULL;
Thomas Jahns's avatar
Thomas Jahns committed
163
  memset(gridptr->uuid, 0, CDI_UUID_SIZE);
Deike Kleberg's avatar
Deike Kleberg committed
164
  gridptr->name         = NULL;
165
  gridptr->vtable       = &cdiGridVtable;
166
  gridptr->extraData    = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
167
168
}

169

170
171
static void
grid_free_components(grid_t *gridptr)
Deike Kleberg's avatar
Deike Kleberg committed
172
{
173
174
175
176
177
178
179
180
  void *p2free[] = { gridptr->mask, gridptr->mask_gme,
                   gridptr->xvals, gridptr->yvals,
                   gridptr->xbounds, gridptr->ybounds,
                   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]);
}
Deike Kleberg's avatar
Deike Kleberg committed
181

182
183
184
void grid_free(grid_t *gridptr)
{
  grid_free_components(gridptr);
Deike Kleberg's avatar
Deike Kleberg committed
185
186
187
  grid_init(gridptr);
}

188
189
static grid_t *
gridNewEntry(cdiResH resH)
190
{
191
  grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t));
192
193
194
195
196
197
198
199
  grid_init(gridptr);
  if (resH == CDI_UNDEFID)
    gridptr->self = reshPut(gridptr, &gridOps);
  else
    {
      gridptr->self = resH;
      reshReplace(resH, gridptr, &gridOps);
    }
200
  return gridptr;
201
202
}

203
static
204
void gridInit (void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
{
206
207
  static int gridInitialized = 0;
  char *env;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
208

209
  if ( gridInitialized ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
210

Thomas Jahns's avatar
Thomas Jahns committed
211
  gridInitialized = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
212

213
214
  env = getenv("GRID_DEBUG");
  if ( env ) GRID_Debug = atoi(env);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
215
216
}

Thomas Jahns's avatar
Thomas Jahns committed
217
218
static void
grid_copy_base_scalar_fields(grid_t *gridptrOrig, grid_t *gridptrDup)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
219
{
Thomas Jahns's avatar
Thomas Jahns committed
220
221
222
223
224
225
  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
226

Thomas Jahns's avatar
Thomas Jahns committed
227
228
229
230
231
232
233
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
234
235
}

236
unsigned cdiGridCount(void)
Thomas Jahns's avatar
Thomas Jahns committed
237
{
238
  return reshCountType(&gridOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
239
240
}

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
static inline void
gridSetXname(grid_t *gridptr, const char *xname)
{
  strncpy(gridptr->xname, xname, CDI_MAX_NAME);
  gridptr->xname[CDI_MAX_NAME - 1] = 0;
}

static inline void
gridSetXlongname(grid_t *gridptr, const char *xlongname)
{
  strncpy(gridptr->xlongname, xlongname, CDI_MAX_NAME);
  gridptr->xlongname[CDI_MAX_NAME - 1] = 0;
}

static inline void
gridSetXunits(grid_t *gridptr, const char *xunits)
{
  strncpy(gridptr->xunits, xunits, CDI_MAX_NAME);
  gridptr->xunits[CDI_MAX_NAME - 1] = 0;
}

static inline void
gridSetYname(grid_t *gridptr, const char *yname)
{
  strncpy(gridptr->yname, yname, CDI_MAX_NAME);
  gridptr->yname[CDI_MAX_NAME - 1] = 0;
}

static inline void
gridSetYlongname(grid_t *gridptr, const char *ylongname)
{
  strncpy(gridptr->ylongname, ylongname, CDI_MAX_NAME);
  gridptr->ylongname[CDI_MAX_NAME - 1] = 0;
}

static inline void
gridSetYunits(grid_t *gridptr, const char *yunits)
{
  strncpy(gridptr->yunits, yunits, CDI_MAX_NAME);
  gridptr->yunits[CDI_MAX_NAME - 1] = 0;
}

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
void
cdiGridTypeInit(grid_t *gridptr, int gridtype, int size)
{

  gridptr->type = gridtype;
  gridptr->size = size;

  switch (gridtype)
    {
    case GRID_CURVILINEAR:
      gridptr->nvertex = 4;
      /* Fall through */
    case GRID_LONLAT:
    case GRID_GAUSSIAN:
    case GRID_GAUSSIAN_REDUCED:
    case GRID_TRAJECTORY:
      {
        if ( gridtype == GRID_TRAJECTORY )
          {
            gridSetXname(gridptr, "tlon");
            gridSetYname(gridptr, "tlat");
          }
        else
          {
            gridSetXname(gridptr, "lon");
            gridSetYname(gridptr, "lat");
          }
        gridSetXlongname(gridptr, "longitude");
        gridSetYlongname(gridptr, "latitude");

        /*
        if ( gridtype == GRID_CURVILINEAR )
          {
            gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
            gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
            gridDefXunits(gridID, "degrees");
            gridDefYunits(gridID, "degrees");
          }
        else
        */
          {
            gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
            gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
            gridSetXunits(gridptr, "degrees_east");
            gridSetYunits(gridptr, "degrees_north");
          }

        break;
      }
    case GRID_UNSTRUCTURED:
      gridptr->xsize = size;
      /* Fall through */
    case GRID_GME:
      {
        gridSetXname(gridptr, "lon");
        gridSetYname(gridptr, "lat");
        gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
        gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
        gridSetXunits(gridptr, "degrees_east");
        gridSetYunits(gridptr, "degrees_north");
        break;
      }
    case GRID_GENERIC:
      {

        /* gridptr->xsize = size; */
        gridSetXname(gridptr, "x");
        gridSetYname(gridptr, "y");
        /*
        strcpy(gridptr->xstdname, "grid_longitude");
        strcpy(gridptr->ystdname, "grid_latitude");
        gridptr->xstdname = xystdname_tab[grid_xystdname_grid_latlon][0];
        gridptr->ystdname = xystdname_tab[grid_xystdname_grid_latlon][1];
        gridDefXunits(gridID, "degrees");
        gridDefYunits(gridID, "degrees");
        */
        break;
      }
    case GRID_LCC2:
    case GRID_SINUSOIDAL:
    case GRID_LAEA:
      {
        gridSetXname(gridptr, "x");
        gridSetYname(gridptr, "y");
        gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
        gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
        gridSetXunits(gridptr, "m");
        gridSetYunits(gridptr, "m");
        break;
      }
    }

}


378
// used also in CDO
379
void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *restrict xvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
380
{
381
  if ( (! (fabs(xinc) > 0)) && xsize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
382
383
    {
      if ( xfirst >= xlast )
Thomas Jahns's avatar
Thomas Jahns committed
384
385
386
387
        {
          while ( xfirst >= xlast ) xlast += 360;
          xinc = (xlast-xfirst)/(xsize);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
388
      else
Thomas Jahns's avatar
Thomas Jahns committed
389
390
391
        {
          xinc = (xlast-xfirst)/(xsize-1);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
392
393
    }

394
  for ( int i = 0; i < xsize; ++i )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
395
396
397
    xvals[i] = xfirst + i*xinc;
}

398
static
399
void calc_gaussgrid(double *restrict yvals, int ysize, double yfirst, double ylast)
400
{
401
  double *restrict yw = (double *) Malloc((size_t)ysize * sizeof(double));
402
  gaussaw(yvals, yw, (size_t)ysize);
403
  Free(yw);
404
  for (int i = 0; i < ysize; i++ )
405
406
407
408
    yvals[i] = asin(yvals[i])/M_PI*180.0;

  if ( yfirst < ylast && yfirst > -90.0 && ylast < 90.0 )
    {
409
410
      int yhsize = ysize/2;
      for (int i = 0; i < yhsize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
411
        {
412
          double ytmp = yvals[i];
Thomas Jahns's avatar
Thomas Jahns committed
413
414
415
          yvals[i] = yvals[ysize-i-1];
          yvals[ysize-i-1] = ytmp;
        }
416
417
418
    }
}

419
// used also in CDO
Thomas Jahns's avatar
Thomas Jahns committed
420
void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
421
{
422
  const double deleps = 0.002;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
423
424
425
426

  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
    {
      if ( ysize > 2 )
Deike Kleberg's avatar
Deike Kleberg committed
427
428
429
430
431
432
	{
	  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 )
	      {
433
		double *restrict ytmp = NULL;
Deike Kleberg's avatar
Deike Kleberg committed
434
		int nstart, lfound = 0;
435
		int ny = (int) (180./(fabs(ylast-yfirst)/(ysize-1)) + 0.5);
Deike Kleberg's avatar
Deike Kleberg committed
436
437
438
		ny -= ny%2;
		if ( ny > ysize && ny < 4096 )
		  {
439
		    ytmp = (double *) Malloc((size_t)ny * sizeof (double));
Deike Kleberg's avatar
Deike Kleberg committed
440
		    calc_gaussgrid(ytmp, ny, yfirst, ylast);
441
442
443
444
445
446
                    {
                      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
447

448
449
		    lfound = (nstart+ysize-1) < ny
                      && fabs(ytmp[nstart+ysize-1] - ylast) < deleps;
450
451
452
453
                    if ( lfound )
                      {
                        for (int i = 0; i < ysize; i++) yvals[i] = ytmp[i+nstart];
                      }
Deike Kleberg's avatar
Deike Kleberg committed
454
455
		  }

456
		if ( !lfound )
Deike Kleberg's avatar
Deike Kleberg committed
457
458
		  {
		    Warning("Cannot calculate gaussian latitudes for lat1 = %g latn = %g!", yfirst, ylast);
459
		    for (int i = 0; i < ysize; i++ ) yvals[i] = 0;
Deike Kleberg's avatar
Deike Kleberg committed
460
461
462
463
		    yvals[0] = yfirst;
		    yvals[ysize-1] = ylast;
		  }

464
		if ( ytmp ) Free(ytmp);
Deike Kleberg's avatar
Deike Kleberg committed
465
466
	      }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
467
      else
Thomas Jahns's avatar
Thomas Jahns committed
468
469
470
471
        {
          yvals[0] = yfirst;
          yvals[ysize-1] = ylast;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
472
473
474
475
    }
  /*     else if ( gridtype == GRID_LONLAT || gridtype == GRID_GENERIC ) */
  else
    {
476
      if ( (! (fabs(yinc) > 0)) && ysize > 1 )
Thomas Jahns's avatar
Thomas Jahns committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
        {
          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
498
499
500

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

501
      for (int i = 0; i < ysize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
502
        yvals[i] = yfirst + i*yinc;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
503
504
505
    }
  /*
    else
506
    Error("unable to calculate values for %s grid!", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
507
508
509
510
  */
}

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

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

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

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

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

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

554
  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
555

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
561
  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
567
568
569

  return (gridID);
}

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

Deike Kleberg's avatar
Deike Kleberg committed
575
  xassert ( gridptr );
576
577
578

  id = gridptr->self;

579
  grid_free_components(gridptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
580
  Free( gridptr );
581

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

585
586
587
588
589
590
/*
@Function  gridDestroy
@Title     Destroy a horizontal Grid

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

@EndFunction
*/
void gridDestroy(int gridID)
{
597
  grid_t *gridptr = gridID2Ptr(gridID);
598
  gridptr->vtable->destroy(gridptr);
599
600
}

601
void gridDestroyP ( void * gridptr )
602
{
603
  ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
604
605
606
}


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

611
  const char *name = gridtype >= 0 && gridtype < size ? Grids[gridtype] : Grids[GRID_GENERIC];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627

  return (name);
}


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

/*
@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
628
629
    @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
630
631

@Description
632
The function @func{gridDefXname} defines the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
633
634
635

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
void gridDefXname(int gridID, const char *xname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
637
{
638
  if ( xname && *xname )
639
    {
640
      grid_t *gridptr = gridID2Ptr(gridID);
641
      gridSetXname(gridptr, xname);
642
      gridMark4Update(gridID);
643
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
644
645
}

646

Uwe Schulzweida's avatar
Uwe Schulzweida committed
647
648
649
650
651
652
/*
@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
653
654
    @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
655
656

@Description
657
The function @func{gridDefXlongname} defines the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
658
659
660

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
661
void gridDefXlongname(int gridID, const char *xlongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
662
{
663
664
  if ( xlongname )
    {
665
      grid_t *gridptr = gridID2Ptr(gridID);
666
      gridSetXlongname(gridptr, xlongname);
667
      gridMark4Update(gridID);
668
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
669
670
671
672
673
674
675
676
}

/*
@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
677
678
    @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
679
680

@Description
681
The function @func{gridDefXunits} defines the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
682
683
684

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
685
void gridDefXunits(int gridID, const char *xunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
{
687
688
  if ( xunits )
    {
689
      grid_t *gridptr = gridID2Ptr(gridID);
690
      gridSetXunits(gridptr, xunits);
691
      gridMark4Update(gridID);
692
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
693
694
695
696
697
698
699
700
}

/*
@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
701
702
    @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
703
704

@Description
705
The function @func{gridDefYname} defines the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
706
707
708

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
709
void gridDefYname(int gridID, const char *yname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
710
{
711
  if ( yname && *yname )
712
    {
713
      grid_t *gridptr = gridID2Ptr(gridID);
714
      gridSetYname(gridptr, yname);
715
      gridMark4Update(gridID);
716
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
717
718
719
720
721
722
723
724
}

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

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

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
733
void gridDefYlongname(int gridID, const char *ylongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
734
{
735
736
  if ( ylongname )
    {
737
      grid_t *gridptr = gridID2Ptr(gridID);
738
      gridSetYlongname(gridptr, ylongname);
739
      gridMark4Update(gridID);
740
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
741
742
743
744
745
746
747
748
}

/*
@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
749
750
    @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
751
752

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

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
757
void gridDefYunits(int gridID, const char *yunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
758
{
759
760
  if ( yunits )
    {
761
      grid_t *gridptr = gridID2Ptr(gridID);
762
      gridSetYunits(gridptr, yunits);
763
      gridMark4Update(gridID);
764
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
765
766
767
768
769
770
}

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

Deike Kleberg's avatar
Deike Kleberg committed
771
@Prototype void gridInqXname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
772
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
773
774
    @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
775
                    returned string. The maximum possible length, in characters, of
776
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
777
778

@Description
779
The function @func{gridInqXname} returns the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
780
781

@Result
782
@func{gridInqXname} returns the name of the X-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
783
784
785
786
787

@EndFunction
*/
void gridInqXname(int gridID, char *xname)
{
788
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
789
790
791
792
793
794
795
796

  strcpy(xname, gridptr->xname);
}

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

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

@Description
805
The function @func{gridInqXlongname} returns the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
806
807

@Result
808
@func{gridInqXlongname} returns the longname of the X-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
809
810
811
812
813

@EndFunction
*/
void gridInqXlongname(int gridID, char *xlongname)
{
814
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
815
816
817
818
819
820
821
822

  strcpy(xlongname, gridptr->xlongname);
}

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

Deike Kleberg's avatar
Deike Kleberg committed
823
@Prototype void gridInqXunits(int gridID, char *units)
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  units    Units 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{gridInqXunits} returns the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
832
833

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

@EndFunction
*/
void gridInqXunits(int gridID, char *xunits)
{
840
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
841
842
843
844
845
846
847

  strcpy(xunits, gridptr->xunits);
}


void gridInqXstdname(int gridID, char *xstdname)
{
848
  grid_t *gridptr = gridID2Ptr(gridID);
849
850
851
852
  if ( gridptr->xstdname )
    strcpy(xstdname, gridptr->xstdname);
  else
    xstdname[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
853
854
855
856
857
858
}

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

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

@Description
867
The function @func{gridInqYname} returns the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
868
869

@Result
870
@func{gridInqYname} returns the name of the Y-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
871
872
873
874
875

@EndFunction
*/
void gridInqYname(int gridID, char *yname)
{
876
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
877
878
879
880
881
882
883
884

  strcpy(yname, gridptr->yname);
}

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

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

@Description
893
The function @func{gridInqYlongname} returns the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
894
895

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

@EndFunction
*/
void gridInqYlongname(int gridID, char *ylongname)
{
902
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
903
904
905
906
907
908
909
910

  strcpy(ylongname, gridptr->ylongname);
}

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

Deike Kleberg's avatar
Deike Kleberg committed
911
@Prototype void gridInqYunits(int gridID, char *units)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
912
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
913
914
    @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
915
                    returned string. The maximum possible length, in characters, of
916
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
917
918

@Description
919
The function @func{gridInqYunits} returns the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
920
921

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

@EndFunction
*/
void gridInqYunits(int gridID, char *yunits)
{
928
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
929
930
931
932
933
934

  strcpy(yunits, gridptr->yunits);
}

void gridInqYstdname(int gridID, char *ystdname)
{
935
  grid_t *gridptr = gridID2Ptr(gridID);
936
937
938
939
  if ( gridptr->ystdname )
    strcpy(ystdname, gridptr->ystdname);
  else
    ystdname[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
940
941
942
943
944
945
946
947
}

/*
@Function  gridInqType
@Title     Get the type of a Grid

@Prototype int gridInqType(int gridID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
948
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
949
950

@Description
951
The function @func{gridInqType} returns the type of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
952
953

@Result
954
@func{gridInqType} returns the type of the grid,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
955
one of the set of predefined CDI grid types.
956
The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
Uwe Schulzweida's avatar
Uwe Schulzweida committed
957
@func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL}, @func{GRID_GME},
958
@func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
959
960
961
962
963

@EndFunction
*/
int gridInqType(int gridID)
{
964
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
965
966
967
968
969
970
971
972
973
974
975

  return (gridptr->type);
}


/*
@Function  gridInqSize
@Title     Get the size of a Grid

@Prototype int gridInqSize(int gridID)
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
976
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
977
978

@Description
979
The function @func{gridInqSize} returns the size of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
980
981

@Result
982
@func{gridInqSize} returns the number of grid points of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
983
984
985
986
987

@EndFunction
*/
int gridInqSize(int gridID)
{
988
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
989

Uwe Schulzweida's avatar
Uwe Schulzweida committed
990
  int size = gridptr->size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
991
992
993
994
995
996
997
998
999

  if ( ! size )
    {
      int xsize, ysize;

      xsize = gridptr->xsize;
      ysize = gridptr->ysize;

      if ( ysize )
1000
        size = xsize * ysize;