grid.c 132 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;
155
156
  gridptr->xdimname[0]  = 0;
  gridptr->ydimname[0]  = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
157
158
159
160
161
162
  gridptr->xname[0]     = 0;
  gridptr->yname[0]     = 0;
  gridptr->xlongname[0] = 0;
  gridptr->ylongname[0] = 0;
  gridptr->xunits[0]    = 0;
  gridptr->yunits[0]    = 0;
163
164
  gridptr->xstdname  = NULL;
  gridptr->ystdname  = NULL;
Thomas Jahns's avatar
Thomas Jahns committed
165
  memset(gridptr->uuid, 0, CDI_UUID_SIZE);
Deike Kleberg's avatar
Deike Kleberg committed
166
  gridptr->name         = NULL;
167
  gridptr->vtable       = &cdiGridVtable;
168
  gridptr->extraData    = NULL;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
169
170
}

171

172
173
static void
grid_free_components(grid_t *gridptr)
Deike Kleberg's avatar
Deike Kleberg committed
174
{
175
176
177
178
179
180
181
182
  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
183

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

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

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

211
  if ( gridInitialized ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
212

Thomas Jahns's avatar
Thomas Jahns committed
213
  gridInitialized = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214

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

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

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

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

243
static inline void
244
gridSetName(char *gridstrname, const char *name)
245
{
246
247
  strncpy(gridstrname, name, CDI_MAX_NAME);
  gridstrname[CDI_MAX_NAME - 1] = 0;
248
249
}

250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
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 )
          {
268
269
            gridSetName(gridptr->xname, "tlon");
            gridSetName(gridptr->yname, "tlat");
270
271
272
          }
        else
          {
273
274
            gridSetName(gridptr->xname, "lon");
            gridSetName(gridptr->yname, "lat");
275
          }
276
277
        gridSetName(gridptr->xlongname, "longitude");
        gridSetName(gridptr->ylongname, "latitude");
278
279
280
281
282
283
284
285
286
287
288
289
290
291

        /*
        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];
292
293
            gridSetName(gridptr->xunits, "degrees_east");
            gridSetName(gridptr->yunits, "degrees_north");
294
295
296
297
298
299
300
301
302
          }

        break;
      }
    case GRID_UNSTRUCTURED:
      gridptr->xsize = size;
      /* Fall through */
    case GRID_GME:
      {
303
304
        gridSetName(gridptr->xname, "lon");
        gridSetName(gridptr->yname, "lat");
305
306
        gridptr->xstdname = xystdname_tab[grid_xystdname_latlon][0];
        gridptr->ystdname = xystdname_tab[grid_xystdname_latlon][1];
307
308
        gridSetName(gridptr->xunits, "degrees_east");
        gridSetName(gridptr->yunits, "degrees_north");
309
310
311
312
313
314
        break;
      }
    case GRID_GENERIC:
      {

        /* gridptr->xsize = size; */
315
316
        gridSetName(gridptr->xname, "x");
        gridSetName(gridptr->yname, "y");
317
318
319
320
321
322
323
324
325
326
327
328
329
330
        /*
        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:
      {
331
332
        gridSetName(gridptr->xname, "x");
        gridSetName(gridptr->yname, "y");
333
334
        gridptr->xstdname = xystdname_tab[grid_xystdname_projection][0];
        gridptr->ystdname = xystdname_tab[grid_xystdname_projection][1];
335
336
        gridSetName(gridptr->xunits, "m");
        gridSetName(gridptr->yunits, "m");
337
338
339
340
341
342
343
        break;
      }
    }

}


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

520
  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
521

522
  gridInit();
523

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
527
  int gridID = gridptr->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
528

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

531
  cdiGridTypeInit(gridptr, gridtype, size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
533
534
535

  return (gridID);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
536
537
static
void gridDestroyKernel( grid_t * gridptr )
538
539
540
{
  int id;

Deike Kleberg's avatar
Deike Kleberg committed
541
  xassert ( gridptr );
542
543
544

  id = gridptr->self;

545
  grid_free_components(gridptr);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
546
  Free( gridptr );
547

548
  reshRemove ( id, &gridOps );
549
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
550

551
552
553
554
555
556
/*
@Function  gridDestroy
@Title     Destroy a horizontal Grid

@Prototype void gridDestroy(int gridID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
557
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
558
559
560
561
562

@EndFunction
*/
void gridDestroy(int gridID)
{
563
  grid_t *gridptr = gridID2Ptr(gridID);
564
  gridptr->vtable->destroy(gridptr);
565
566
}

567
void gridDestroyP ( void * gridptr )
568
{
569
  ((grid_t *)gridptr)->vtable->destroy((grid_t *)gridptr);
570
571
572
}


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

577
  const char *name = gridtype >= 0 && gridtype < size ? Grids[gridtype] : Grids[GRID_GENERIC];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
578
579
580
581
582
583
584
585
586
587

  return (name);
}


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

588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
/*
@Function  gridDefXdimname
@Title     Define the dimension name of a X-axis

@Prototype void gridDefXdimname(int gridID, const char *dimname)
@Parameter
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  dimname  Dimension name of the X-axis.

@Description
The function @func{gridDefXdimname} defines the dimension name of a X-axis.

@EndFunction
*/
void gridDefXdimname(int gridID, const char *xdimname)
{
  if ( xdimname && *xdimname )
    {
      grid_t *gridptr = gridID2Ptr(gridID);
      gridSetName(gridptr->xdimname, xdimname);
      gridMark4Update(gridID);
    }
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
612
613
614
615
616
617
/*
@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
618
619
    @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
620
621

@Description
622
The function @func{gridDefXname} defines the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
623
624
625

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
626
void gridDefXname(int gridID, const char *xname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
{
628
  if ( xname && *xname )
629
    {
630
      grid_t *gridptr = gridID2Ptr(gridID);
631
      gridSetName(gridptr->xname, xname);
632
      gridMark4Update(gridID);
633
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
634
635
636
637
638
639
640
641
}

/*
@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
642
643
    @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
644
645

@Description
646
The function @func{gridDefXlongname} defines the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
647
648
649

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
650
void gridDefXlongname(int gridID, const char *xlongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
651
{
652
653
  if ( xlongname )
    {
654
      grid_t *gridptr = gridID2Ptr(gridID);
655
      gridSetName(gridptr->xlongname, xlongname);
656
      gridMark4Update(gridID);
657
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
658
659
660
661
662
663
664
665
}

/*
@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
666
667
    @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
668
669

@Description
670
The function @func{gridDefXunits} defines the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
671
672
673

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
674
void gridDefXunits(int gridID, const char *xunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
675
{
676
677
  if ( xunits )
    {
678
      grid_t *gridptr = gridID2Ptr(gridID);
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
      gridSetName(gridptr->xunits, xunits);
      gridMark4Update(gridID);
    }
}

/*
@Function  gridDefYdimname
@Title     Define the dimension name of a Y-axis

@Prototype void gridDefYdimname(int gridID, const char *dimname)
@Parameter
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
    @Item  dimname  Dimension name of the Y-axis.

@Description
The function @func{gridDefYdimname} defines the dimension name of a Y-axis.

@EndFunction
*/
void gridDefYdimname(int gridID, const char *ydimname)
{
  if ( ydimname && *ydimname )
    {
      grid_t *gridptr = gridID2Ptr(gridID);
      gridSetName(gridptr->ydimname, ydimname);
704
      gridMark4Update(gridID);
705
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
706
707
708
709
710
711
712
713
}

/*
@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
714
715
    @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
716
717

@Description
718
The function @func{gridDefYname} defines the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
719
720
721

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
722
void gridDefYname(int gridID, const char *yname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
723
{
724
  if ( yname && *yname )
725
    {
726
      grid_t *gridptr = gridID2Ptr(gridID);
727
      gridSetName(gridptr->yname, yname);
728
      gridMark4Update(gridID);
729
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730
731
732
733
734
735
736
737
}

/*
@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
738
739
    @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
740
741

@Description
742
The function @func{gridDefYlongname} defines the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
743
744
745

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
746
void gridDefYlongname(int gridID, const char *ylongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
747
{
748
749
  if ( ylongname )
    {
750
      grid_t *gridptr = gridID2Ptr(gridID);
751
      gridSetName(gridptr->ylongname, ylongname);
752
      gridMark4Update(gridID);
753
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
754
755
756
757
758
759
760
761
}

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

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

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
770
void gridDefYunits(int gridID, const char *yunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
771
{
772
773
  if ( yunits )
    {
774
      grid_t *gridptr = gridID2Ptr(gridID);
775
      gridSetName(gridptr->yunits, yunits);
776
      gridMark4Update(gridID);
777
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
778
779
780
781
782
783
}

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

Deike Kleberg's avatar
Deike Kleberg committed
784
@Prototype void gridInqXname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
786
787
    @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
788
                    returned string. The maximum possible length, in characters, of
789
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
790
791

@Description
792
The function @func{gridInqXname} returns the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
793
794

@Result
795
@func{gridInqXname} returns the name of the X-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
796
797
798
799
800

@EndFunction
*/
void gridInqXname(int gridID, char *xname)
{
801
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
803
804
805
806
807
808
809

  strcpy(xname, gridptr->xname);
}

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

Deike Kleberg's avatar
Deike Kleberg committed
810
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
811
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
812
813
    @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
814
                    returned string. The maximum possible length, in characters, of
815
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
816
817

@Description
818
The function @func{gridInqXlongname} returns the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
819
820

@Result
821
@func{gridInqXlongname} returns the longname of the X-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
822
823
824
825
826

@EndFunction
*/
void gridInqXlongname(int gridID, char *xlongname)
{
827
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828
829
830
831
832
833
834
835

  strcpy(xlongname, gridptr->xlongname);
}

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

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

@Description
844
The function @func{gridInqXunits} returns the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
845
846

@Result
847
@func{gridInqXunits} returns the units of the X-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
848
849
850
851
852

@EndFunction
*/
void gridInqXunits(int gridID, char *xunits)
{
853
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
854
855
856
857
858
859
860

  strcpy(xunits, gridptr->xunits);
}


void gridInqXstdname(int gridID, char *xstdname)
{
861
  grid_t *gridptr = gridID2Ptr(gridID);
862
863
864
865
  if ( gridptr->xstdname )
    strcpy(xstdname, gridptr->xstdname);
  else
    xstdname[0] = 0;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
866
867
868
869
870
871
}

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

Deike Kleberg's avatar
Deike Kleberg committed
872
@Prototype void gridInqYname(int gridID, char *name)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
873
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
874
875
    @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
876
                    returned string. The maximum possible length, in characters, of
877
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
878
879

@Description
880
The function @func{gridInqYname} returns the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
881
882

@Result
883
@func{gridInqYname} returns the name of the Y-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
884
885
886
887
888

@EndFunction
*/
void gridInqYname(int gridID, char *yname)
{
889
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
890
891
892
893
894
895
896
897

  strcpy(yname, gridptr->yname);
}

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

Deike Kleberg's avatar
Deike Kleberg committed
898
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
899
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
900
901
    @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
902
                    returned string. The maximum possible length, in characters, of
903
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
904
905

@Description
906
The function @func{gridInqYlongname} returns the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
907
908

@Result
909
@func{gridInqYlongname} returns the longname of the Y-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
910
911
912
913
914

@EndFunction
*/
void gridInqYlongname(int gridID, char *ylongname)
{
915
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
916
917
918
919
920
921
922
923

  strcpy(ylongname, gridptr->ylongname);
}

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

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

@Description
932
The function @func{gridInqYunits} returns the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
933
934

@Result
935
@func{gridInqYunits} returns the units of the Y-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
936
937
938
939
940

@EndFunction
*/
void gridInqYunits(int gridID, char *yunits)
{
941
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
942
943
944
945
946
947

  strcpy(yunits, gridptr->yunits);
}

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

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

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

@Description
964
The function @func{gridInqType} returns the type of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
965
966

@Result
967
@func{gridInqType} returns the type of the grid,
Uwe Schulzweida's avatar
Uwe Schulzweida committed
968
one of the set of predefined CDI grid types.
969
The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
Uwe Schulzweida's avatar
Uwe Schulzweida committed
970
@func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL}, @func{GRID_GME},
971
@func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
972
973
974
975
976

@EndFunction
*/
int gridInqType(int gridID)
{
977
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
978
979
980
981
982
983
984
985
986
987
988

  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
989
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
990
991

@Description
992
The function @func{gridInqSize} returns the size of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
993
994

@Result
995
@func{gridInqSize} returns the number of grid points of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
996
997
998
999
1000

@EndFunction
*/
int gridInqSize(int gridID)
{