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

#include <string.h>
6
#include <float.h>  /* FLT_EPSILON */
7
#include <limits.h> /* INT_MAX     */
8

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

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

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

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

};


Uwe Schulzweida's avatar
Uwe Schulzweida committed
63

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

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

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

83
#define gridID2Ptr(gridID) (grid_t *)reshGetVal(gridID, &gridOps)
84
#define gridMark4Update(gridID) reshSetStatus(gridID, &gridOps, RESH_DESYNC_IN_USE)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
85

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

161

Deike Kleberg's avatar
Deike Kleberg committed
162
163
void grid_free(grid_t *gridptr)
{
164
165
166
167
168
169
170
171
172
173
  if ( gridptr->mask      ) Free(gridptr->mask);
  if ( gridptr->mask_gme  ) Free(gridptr->mask_gme);
  if ( gridptr->xvals     ) Free(gridptr->xvals);
  if ( gridptr->yvals     ) Free(gridptr->yvals);
  if ( gridptr->area      ) Free(gridptr->area);
  if ( gridptr->xbounds   ) Free(gridptr->xbounds);
  if ( gridptr->ybounds   ) Free(gridptr->ybounds);
  if ( gridptr->rowlon    ) Free(gridptr->rowlon);
  if ( gridptr->reference ) Free(gridptr->reference);
  if ( gridptr->name      ) Free(gridptr->name);
Deike Kleberg's avatar
Deike Kleberg committed
174
175
176
177

  grid_init(gridptr);
}

178
179
static grid_t *
gridNewEntry(cdiResH resH)
180
{
181
  grid_t *gridptr = (grid_t*) Malloc(sizeof(grid_t));
182
183
184
185
186
187
188
189
  grid_init(gridptr);
  if (resH == CDI_UNDEFID)
    gridptr->self = reshPut(gridptr, &gridOps);
  else
    {
      gridptr->self = resH;
      reshReplace(resH, gridptr, &gridOps);
    }
190
  return gridptr;
191
192
}

193
static
194
void gridInit (void)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
195
{
196
197
  static int gridInitialized = 0;
  char *env;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
198

199
  if ( gridInitialized ) return;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
200

Thomas Jahns's avatar
Thomas Jahns committed
201
  gridInitialized = 1;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
202

203
204
  env = getenv("GRID_DEBUG");
  if ( env ) GRID_Debug = atoi(env);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
205
206
}

207
208
static
void grid_copy(grid_t *gridptr2, grid_t *gridptr1)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
209
210
211
212
{
  int gridID2;

  gridID2 = gridptr2->self;
213
  memcpy(gridptr2, gridptr1, sizeof(grid_t));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
214
215
216
  gridptr2->self = gridID2;
}

217
unsigned cdiGridCount(void)
Thomas Jahns's avatar
Thomas Jahns committed
218
{
219
  return reshCountType(&gridOps);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
220
221
}

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
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
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;
}

264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
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
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;
      }
    }

}


359
360
// used also in CDO
void gridGenXvals(int xsize, double xfirst, double xlast, double xinc, double *xvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
361
{
362
  if ( (! (fabs(xinc) > 0)) && xsize > 1 )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
363
364
    {
      if ( xfirst >= xlast )
Thomas Jahns's avatar
Thomas Jahns committed
365
366
367
368
        {
          while ( xfirst >= xlast ) xlast += 360;
          xinc = (xlast-xfirst)/(xsize);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
369
      else
Thomas Jahns's avatar
Thomas Jahns committed
370
371
372
        {
          xinc = (xlast-xfirst)/(xsize-1);
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
373
374
    }

375
  for ( int i = 0; i < xsize; ++i )
Uwe Schulzweida's avatar
Uwe Schulzweida committed
376
377
378
    xvals[i] = xfirst + i*xinc;
}

379
380
static
void calc_gaussgrid(double *yvals, int ysize, double yfirst, double ylast)
381
{
382
  double *restrict yw = (double *) Malloc((size_t)ysize * sizeof(double));
383
  gaussaw(yvals, yw, (size_t)ysize);
384
  Free(yw);
385
  for (int i = 0; i < ysize; i++ )
386
387
388
389
    yvals[i] = asin(yvals[i])/M_PI*180.0;

  if ( yfirst < ylast && yfirst > -90.0 && ylast < 90.0 )
    {
390
391
      int yhsize = ysize/2;
      for (int i = 0; i < yhsize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
392
        {
393
          double ytmp = yvals[i];
Thomas Jahns's avatar
Thomas Jahns committed
394
395
396
          yvals[i] = yvals[ysize-i-1];
          yvals[ysize-i-1] = ytmp;
        }
397
398
399
    }
}

400
// used also in CDO
Thomas Jahns's avatar
Thomas Jahns committed
401
void gridGenYvals(int gridtype, int ysize, double yfirst, double ylast, double yinc, double *restrict yvals)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
402
{
403
  const double deleps = 0.002;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
404
405
406
407

  if ( gridtype == GRID_GAUSSIAN || gridtype == GRID_GAUSSIAN_REDUCED )
    {
      if ( ysize > 2 )
Deike Kleberg's avatar
Deike Kleberg committed
408
409
410
411
412
413
	{
	  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 )
	      {
414
		double *restrict ytmp = NULL;
Deike Kleberg's avatar
Deike Kleberg committed
415
		int nstart, lfound = 0;
416
		int ny = (int) (180./fabs(ylast-yfirst)/(ysize-1) + 0.5);
Deike Kleberg's avatar
Deike Kleberg committed
417
418
419
		ny -= ny%2;
		if ( ny > ysize && ny < 4096 )
		  {
420
		    ytmp = (double *) Malloc((size_t)ny * sizeof (double));
Deike Kleberg's avatar
Deike Kleberg committed
421
		    calc_gaussgrid(ytmp, ny, yfirst, ylast);
422
423
424
425
426
427
                    {
                      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
428

429
430
		    lfound = (nstart+ysize-1) < ny
                      && fabs(ytmp[nstart+ysize-1] - ylast) < deleps;
431
432
433
434
                    if ( lfound )
                      {
                        for (int i = 0; i < ysize; i++) yvals[i] = ytmp[i+nstart];
                      }
Deike Kleberg's avatar
Deike Kleberg committed
435
436
		  }

437
		if ( !lfound )
Deike Kleberg's avatar
Deike Kleberg committed
438
439
		  {
		    Warning("Cannot calculate gaussian latitudes for lat1 = %g latn = %g!", yfirst, ylast);
440
		    for (int i = 0; i < ysize; i++ ) yvals[i] = 0;
Deike Kleberg's avatar
Deike Kleberg committed
441
442
443
444
		    yvals[0] = yfirst;
		    yvals[ysize-1] = ylast;
		  }

445
		if ( ytmp ) Free(ytmp);
Deike Kleberg's avatar
Deike Kleberg committed
446
447
	      }
	}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
448
      else
Thomas Jahns's avatar
Thomas Jahns committed
449
450
451
452
        {
          yvals[0] = yfirst;
          yvals[ysize-1] = ylast;
        }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
453
454
455
456
    }
  /*     else if ( gridtype == GRID_LONLAT || gridtype == GRID_GENERIC ) */
  else
    {
457
      if ( (! (fabs(yinc) > 0)) && ysize > 1 )
Thomas Jahns's avatar
Thomas Jahns committed
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
        {
          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
479
480
481

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

482
      for (int i = 0; i < ysize; i++ )
Thomas Jahns's avatar
Thomas Jahns committed
483
        yvals[i] = yfirst + i*yinc;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
484
485
486
    }
  /*
    else
487
    Error("unable to calculate values for %s grid!", gridNamePtr(gridtype));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
488
489
490
491
  */
}

/*
492
@Function  gridCreate
493
@Title     Create a horizontal Grid
Uwe Schulzweida's avatar
Uwe Schulzweida committed
494

495
@Prototype int gridCreate(int gridtype, int size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
496
497
@Parameter
    @Item  gridtype  The type of the grid, one of the set of predefined CDI grid types.
498
                     The valid CDI grid types are @func{GRID_GENERIC}, @func{GRID_GAUSSIAN},
Uwe Schulzweida's avatar
Uwe Schulzweida committed
499
                     @func{GRID_LONLAT}, @func{GRID_LCC}, @func{GRID_SPECTRAL},
500
                     @func{GRID_GME}, @func{GRID_CURVILINEAR} and @func{GRID_UNSTRUCTURED} and.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
501
502
503
    @Item  size      Number of gridpoints.

@Description
504
The function @func{gridCreate} creates a horizontal Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
505
506

@Result
507
@func{gridCreate} returns an identifier to the Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
508
509

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

@Source
Uwe Schulzweida's avatar
Uwe Schulzweida committed
513
514
#include "cdi.h"
   ...
515
516
#define  nlon  12
#define  nlat   6
Uwe Schulzweida's avatar
Uwe Schulzweida committed
517
   ...
518
519
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
520
521
int gridID;
   ...
522
523
524
gridID = gridCreate(GRID_LONLAT, nlon*nlat);
gridDefXsize(gridID, nlon);
gridDefYsize(gridID, nlat);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
525
526
527
528
gridDefXvals(gridID, lons);
gridDefYvals(gridID, lats);
   ...
@EndSource
Uwe Schulzweida's avatar
Uwe Schulzweida committed
529
530
@EndFunction
*/
531
int gridCreate(int gridtype, int size)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
532
{
533
  if ( CDI_Debug ) Message("gridtype=%s  size=%d", gridNamePtr(gridtype), size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
534

535
  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
536

537
  gridInit();
538

Uwe Schulzweida's avatar
Uwe Schulzweida committed
539
  grid_t *gridptr = gridNewEntry(CDI_UNDEFID);
540
  if ( ! gridptr ) Error("No memory");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
541

Uwe Schulzweida's avatar
Uwe Schulzweida committed
542
  int gridID = gridptr->self;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
543

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

546
  cdiGridTypeInit(gridptr, gridtype, size);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
547
548
549
550

  return (gridID);
}

Uwe Schulzweida's avatar
Uwe Schulzweida committed
551
552
static
void gridDestroyKernel( grid_t * gridptr )
553
554
555
{
  int id;

Deike Kleberg's avatar
Deike Kleberg committed
556
  xassert ( gridptr );
557
558
559

  id = gridptr->self;

560
561
562
563
564
565
566
567
568
  if ( gridptr->mask      ) Free(gridptr->mask);
  if ( gridptr->mask_gme  ) Free(gridptr->mask_gme);
  if ( gridptr->xvals     ) Free(gridptr->xvals);
  if ( gridptr->yvals     ) Free(gridptr->yvals);
  if ( gridptr->area      ) Free(gridptr->area);
  if ( gridptr->xbounds   ) Free(gridptr->xbounds);
  if ( gridptr->ybounds   ) Free(gridptr->ybounds);
  if ( gridptr->rowlon    ) Free(gridptr->rowlon);
  if ( gridptr->reference ) Free(gridptr->reference);
569

Uwe Schulzweida's avatar
Uwe Schulzweida committed
570
  Free( gridptr );
571

572
  reshRemove ( id, &gridOps );
573
}
Uwe Schulzweida's avatar
Uwe Schulzweida committed
574

575
576
577
578
579
580
/*
@Function  gridDestroy
@Title     Destroy a horizontal Grid

@Prototype void gridDestroy(int gridID)
@Parameter
Deike Kleberg's avatar
Deike Kleberg committed
581
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate}.
582
583
584
585
586

@EndFunction
*/
void gridDestroy(int gridID)
{
587
  grid_t *gridptr = gridID2Ptr(gridID);
588

589
  gridDestroyKernel ( gridptr );
590
591
}

592
void gridDestroyP ( void * gridptr )
593
{
594
  gridDestroyKernel (( grid_t * ) gridptr );
595
596
597
}


598
const char *gridNamePtr(int gridtype)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
599
{
600
  int size = (int) (sizeof(Grids)/sizeof(Grids[0]));
Uwe Schulzweida's avatar
Uwe Schulzweida committed
601

602
  const char *name = gridtype >= 0 && gridtype < size ? Grids[gridtype] : Grids[GRID_GENERIC];
Uwe Schulzweida's avatar
Uwe Schulzweida committed
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618

  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
619
620
    @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
621
622

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

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
627
void gridDefXname(int gridID, const char *xname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
628
{
629
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
630

631
632
  if ( xname )
    {
633
      gridSetXname(gridptr, xname);
634
      gridMark4Update(gridID);
635
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
636
637
}

638

Uwe Schulzweida's avatar
Uwe Schulzweida committed
639
640
641
642
643
644
/*
@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
645
646
    @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
647
648

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

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

/*
@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
669
670
    @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
671
672

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

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
677
void gridDefXunits(int gridID, const char *xunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
678
{
679
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
680

681
682
  if ( xunits )
    {
683
      gridSetXunits(gridptr, xunits);
684
      gridMark4Update(gridID);
685
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
686
687
688
689
690
691
692
693
}

/*
@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
694
695
    @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
696
697

@Description
698
The function @func{gridDefYname} defines the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
699
700
701

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
702
void gridDefYname(int gridID, const char *yname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
703
{
704
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
705

706
707
  if ( yname )
    {
708
      gridSetYname(gridptr, yname);
709
      gridMark4Update(gridID);
710
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
711
712
713
714
715
716
717
718
}

/*
@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
719
720
    @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
721
722

@Description
723
The function @func{gridDefYlongname} defines the longname of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
724
725
726

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
727
void gridDefYlongname(int gridID, const char *ylongname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
728
{
729
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
730

731
732
  if ( ylongname )
    {
733
      gridSetYlongname(gridptr, ylongname);
734
      gridMark4Update(gridID);
735
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
736
737
738
739
740
741
742
743
}

/*
@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
744
745
    @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
746
747

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

@EndFunction
*/
Uwe Schulzweida's avatar
Uwe Schulzweida committed
752
void gridDefYunits(int gridID, const char *yunits)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
753
{
754
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
755

756
757
  if ( yunits )
    {
758
      gridSetYunits(gridptr, yunits);
759
      gridMark4Update(gridID);
760
    }
Uwe Schulzweida's avatar
Uwe Schulzweida committed
761
762
763
764
765
766
}

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

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

@Description
775
The function @func{gridInqXname} returns the name of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
776
777

@Result
778
@func{gridInqXname} returns the name of the X-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
779
780
781
782
783

@EndFunction
*/
void gridInqXname(int gridID, char *xname)
{
784
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
785
786
787
788
789
790
791
792

  strcpy(xname, gridptr->xname);
}

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

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

@Description
801
The function @func{gridInqXlongname} returns the longname of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
802
803

@Result
804
@func{gridInqXlongname} returns the longname of the X-axis to the parameter longname.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
805
806
807
808
809

@EndFunction
*/
void gridInqXlongname(int gridID, char *xlongname)
{
810
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
811
812
813
814
815
816
817
818

  strcpy(xlongname, gridptr->xlongname);
}

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

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

@Description
827
The function @func{gridInqXunits} returns the units of a X-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
828
829

@Result
830
@func{gridInqXunits} returns the units of the X-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
831
832
833
834
835

@EndFunction
*/
void gridInqXunits(int gridID, char *xunits)
{
836
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
837
838
839
840
841
842
843

  strcpy(xunits, gridptr->xunits);
}


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

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

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

@Description
863
The function @func{gridInqYname} returns the name of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
864
865

@Result
866
@func{gridInqYname} returns the name of the Y-axis to the parameter name.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
867
868
869
870
871

@EndFunction
*/
void gridInqYname(int gridID, char *yname)
{
872
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
873
874
875
876
877
878
879
880

  strcpy(yname, gridptr->yname);
}

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

Deike Kleberg's avatar
Deike Kleberg committed
881
@Prototype void gridInqXlongname(int gridID, char *longname)
Uwe Schulzweida's avatar
Uwe Schulzweida committed
882
@Parameter
Uwe Schulzweida's avatar
Uwe Schulzweida committed
883
884
    @Item  gridID   Grid ID, from a previous call to @fref{gridCreate} or @fref{vlistInqVarGrid}.
    @Item  longname Longname of the Y-axis. The caller must allocate space for the
Deike Kleberg's avatar
Deike Kleberg committed
885
                    returned string. The maximum possible length, in characters, of
886
                    the string is given by the predefined constant @func{CDI_MAX_NAME}.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
887
888

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

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

@EndFunction
*/
void gridInqYlongname(int gridID, char *ylongname)
{
898
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
899
900
901
902
903
904
905
906

  strcpy(ylongname, gridptr->ylongname);
}

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

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

@Description
915
The function @func{gridInqYunits} returns the units of a Y-axis.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
916
917

@Result
918
@func{gridInqYunits} returns the units of the Y-axis to the parameter units.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
919
920
921
922
923

@EndFunction
*/
void gridInqYunits(int gridID, char *yunits)
{
924
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
925
926
927
928
929
930

  strcpy(yunits, gridptr->yunits);
}

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

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

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

@Description
947
The function @func{gridInqType} returns the type of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
948
949

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

@EndFunction
*/
int gridInqType(int gridID)
{
960
  grid_t *gridptr = gridID2Ptr(gridID);
Uwe Schulzweida's avatar
Uwe Schulzweida committed
961
962
963
964
965
966
967
968
969
970
971

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

@Description
975
The function @func{gridInqSize} returns the size of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
976
977

@Result
978
@func{gridInqSize} returns the number of grid points of a Grid.
Uwe Schulzweida's avatar
Uwe Schulzweida committed
979
980
981
982
983

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

Uwe Schulzweida's avatar
Uwe Schulzweida committed
986
  int size = gridptr->size;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
987
988
989
990
991
992
993
994
995

  if ( ! size )
    {
      int xsize, ysize;

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

      if ( ysize )
Thomas Jahns's avatar
Thomas Jahns committed
996
        size = xsize *ysize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
997
      else
Thomas Jahns's avatar
Thomas Jahns committed
998
        size = xsize;
Uwe Schulzweida's avatar
Uwe Schulzweida committed
999

Thomas Jahns's avatar
Thomas Jahns committed
1000
      gridptr->size = size;
For faster browsing, not all history is shown. View entire blame