Samplegrid.c 7.99 KB
Newer Older
1
2
3
4
5
6
7
8
/*
   This module "SampleGrid" contains the following operators:

    samplegrid      Resample current grid with given factor, typically 2 (which will half the resolution);
                    tested on curvilinear and LCC grids;
    subgrid         Similar to selindexbox but this operator works for LCC grids (tested on HARMONIE NWP model).
*/

Uwe Schulzweida's avatar
Uwe Schulzweida committed
9
#include <cdi.h>
10
11
#include "cdo_int.h"
#include "pstream.h"
Uwe Schulzweida's avatar
Uwe Schulzweida committed
12
#include "grid.h"
13
14
15


static
16
void sampleData(double *array1, int gridID1, double *array2, int gridID2, int resampleFactor)
17
{
18
19
  long nlon1 = gridInqXsize(gridID1);
  long nlat1 = gridInqYsize(gridID1);
20

21
22
  long nlon2 = gridInqXsize(gridID2);
  long nlat2 = gridInqYsize(gridID2);
23

24
25
26
  if ( cdoDebugExt >= 100 )
    cdoPrint("sampleData():: (nlon1: %d; nlat1: %d) => (nlon2: %d; nlat2: %d); gridID1: %d; gridID2: %d; resampleFactor: %d)",
             nlon1,nlat1, nlon2,nlat2, gridID1, gridID2, resampleFactor);
27

28
29
30
  for ( long ilat1 = 0; ilat1 < nlat1; ilat1+=resampleFactor )
    for ( long ilon1 = 0; ilon1 < nlon1; ilon1+=resampleFactor )
      *array2++ = array1[ilat1*nlon1 + ilon1];
31
32
33
}

static
34
void cropData(double *array1, int gridID1, double *array2, int gridID2, int subI0, int subI1, int  subJ0, int  subJ1 )
35
{
36
37
38
  long nlon1 = gridInqXsize(gridID1);
  long nlon2 = gridInqXsize(gridID2);
  long rowLen = subI1 - subI0 + 1; // must be same as   nlon1
39

40
41
  if ( rowLen!= nlon2 )
    cdoAbort("cropData() rowLen!= nlon2 [%d != %d]", rowLen, nlon2);
42

Uwe Schulzweida's avatar
Uwe Schulzweida committed
43
  if ( cdoDebugExt>=10 ) cdoPrint("cropData(%d,%d,%d,%d) ...\n", subI0, subI1, subJ0, subJ1 );
44

45
46
  long array2Idx = 0;
  for ( long ilat1 = subJ0; ilat1 <= subJ1; ilat1++ ) // copy the last row as well..
47
    {
48
49
50
      //if ( cdoDebugExt>20 ) cdoPrint("cropData(): ilat1=%d; subJ0=%d; subJ1=%d; rowLen=%d ", ilat1, subJ0, subJ1, rowLen );
      memcpy((void*)&array2[array2Idx], (void*)&array1[ilat1*nlon1 + subI0], rowLen*sizeof(double));
      array2Idx += rowLen;
51
52
53
54
    }
}


55
void *Samplegrid(void *argument)
56
{
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  int nrecs;
  int varID, levelID;
  int resampleFactor;
  int subI0 = 0, subI1 = 0, subJ0 = 0, subJ1 = 0;
  int index;
  int nmiss;
  typedef struct {
    int gridSrcID, gridIDsampled;
    int *cellidx, nvals;
    int subI0,subI1, subJ0, subJ1;
  } sbox_t;

  cdoInitialize(argument);

  int SAMPLEGRID  = cdoOperatorAdd("samplegrid",  0, 0, "resample factor, typically 2 (which will half the resolution)");
  int SUBGRID  = cdoOperatorAdd("subgrid",  0, 0, " sub-grid indices: i0,i1,j0,j1");

  int operatorID = cdoOperatorID();

  int nch = operatorArgc();

  if ( operatorID == SAMPLEGRID )
79
    {
80
      if ( cdoDebugExt ) cdoPrint("samplegrid operator requested..");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
81
      if ( nch < 1 ) cdoAbort("Number of input arguments < 1; At least 1 argument needed: resample-factor (2,3,4, .. etc)");
82
      resampleFactor = parameter2int(operatorArgv()[0]);
83

84
      if ( cdoDebugExt ) cdoPrint("resampleFactor = %d", resampleFactor);
85
    }
86
  else if ( operatorID == SUBGRID )
87
    {
88
      if ( cdoDebugExt ) cdoPrint("subgrid operator requested..");
Uwe Schulzweida's avatar
Uwe Schulzweida committed
89
      if ( nch < 4 ) cdoAbort("Number of input arguments < 4; Must specify sub-grid indices: i0,i1,j0,j1; This works only with LCC grid. For other grids use: selindexbox");
90
91
92
93
      subI0 = parameter2int(operatorArgv()[0]);
      subI1 = parameter2int(operatorArgv()[1]);
      subJ0 = parameter2int(operatorArgv()[2]);
      subJ1 = parameter2int(operatorArgv()[3]);
94
    }
95
96
  else
    cdoAbort("Unknown operator ...");
97

98
  int streamID1 = streamOpenRead(cdoStreamName(0));
99

100
101
  int vlistID1 = streamInqVlist(streamID1);
  int vlistID2 = vlistDuplicate(vlistID1);
102

103
104
105
  int taxisID1 = vlistInqTaxis(vlistID1);
  int taxisID2 = taxisDuplicate(taxisID1);
  vlistDefTaxis(vlistID2, taxisID2);
106

107
108
109
  int nvars = vlistNvars(vlistID1);
  bool *vars  = (bool *) Malloc(nvars*sizeof(bool));
  for ( varID = 0; varID < nvars; varID++ ) vars[varID] = false;
110

111
  int ngrids = vlistNgrids(vlistID1);
112

113
  if ( cdoDebugExt ) cdoPrint("ngrids = %d", ngrids);
114

115
  sbox_t *sbox = (sbox_t *) Malloc(ngrids*sizeof(sbox_t));
116

117
  for ( int index = 0; index < ngrids; index++ )
118
    {
119
120
      int gridSrcID = vlistGrid(vlistID1, index);
      int gridIDsampled = -1;
121

122
      int gridtype = gridInqType(gridSrcID);
123
      if ( ! (gridtype == GRID_GAUSSIAN || gridtype == GRID_LONLAT || gridtype == GRID_PROJECTION ||
124
              gridtype == GRID_CURVILINEAR || gridtype == GRID_GENERIC || gridtype == GRID_LCC) )
125
126
127
        cdoAbort("Unsupported gridtype: %s", gridNamePtr(gridtype));

      if ( operatorID == SAMPLEGRID )
128
        {
129
130
131
132
133
134
135
136
          gridIDsampled = cdo_define_sample_grid(gridSrcID, resampleFactor);
        }
      else if ( operatorID == SUBGRID )
        {
          if ( gridtype != GRID_LCC )
            cdoAbort("Unsupported grid type: %s; This works only with LCC grid. For other grids use: selindexbox", gridNamePtr(gridtype));

          int gridIDcurvl = gridToCurvilinear(gridSrcID, 1);
137

138
          gridIDsampled = cdo_define_subgrid_grid(gridSrcID, gridIDcurvl, subI0, subI1, subJ0, subJ1);
139
140
141
          
          gridDestroy(gridIDcurvl);
        }
142

143
144
      sbox[index].gridSrcID = gridSrcID;
      sbox[index].gridIDsampled = gridIDsampled;
145

146
147
      // if ( cdoDebugExt>=10 ) cdo_print_grid(gridSrcID, 1);
      // if ( cdoDebugExt>=10 ) cdo_print_grid(gridIDsampled, 1);
148
149
150
151
152
      
      vlistChangeGridIndex(vlistID2, index, gridIDsampled);
      for ( varID = 0; varID < nvars; varID++ )
        if ( gridSrcID == vlistInqVarGrid(vlistID1, varID) )
          vars[varID] = true;
153
154
    }

155
  if ( cdoDebugExt )
156
    {
157
158
      if ( operatorID == SAMPLEGRID ) cdoPrint("Resampled grid has been created.");
      if ( operatorID == SUBGRID    ) cdoPrint("Sub-grid has been created.");
159
160
    }

161
  int streamID2 = streamOpenWrite(cdoStreamName(1), cdoFiletype());
162

163
  streamDefVlist(streamID2, vlistID2);
164

165
166
167
  int gridsize = vlistGridsizeMax(vlistID1);
  if ( vlistNumber(vlistID1) != CDI_REAL ) gridsize *= 2;
  double *array1 = (double *) Malloc(gridsize*sizeof(double));
168

169
170
171
  int gridsize2 = vlistGridsizeMax(vlistID2);
  if ( vlistNumber(vlistID2) != CDI_REAL ) gridsize2 *= 2;
  double *array2 = (double *) Malloc(gridsize2*sizeof(double));
172

173
  if ( cdoDebugExt ) cdoPrint("gridsize = %ld, gridsize2 = %ld", gridsize, gridsize2);
174

175
176
  int tsID = 0;
  while ( (nrecs = streamInqTimestep(streamID1, tsID)) )
177
    {
178
      taxisCopyTimestep(taxisID2, taxisID1);
179

180
      streamDefTimestep(streamID2, tsID);
181

182
      for ( int recID = 0; recID < nrecs; recID++ )
183
        {
184
185
          streamInqRecord(streamID1, &varID, &levelID);
          streamReadRecord(streamID1, array1, &nmiss);
186

187
          streamDefRecord(streamID2, varID, levelID);
188

189
          if ( cdoDebugExt>=20 ) cdoPrint("Processing record (%d) of %d.",recID, nrecs);
190

191
          if ( vars[varID] )
192
            {
193
              int gridSrcID = vlistInqVarGrid(vlistID1, varID);
194

195
196
              for ( index = 0; index < ngrids; index++ )
                if ( gridSrcID == sbox[index].gridSrcID ) break;
197

198
              if ( index == ngrids ) cdoAbort("Internal problem, grid not found!");
199

200
201
              int gridIDsampled = sbox[index].gridIDsampled;
              gridsize2 = gridInqSize(gridIDsampled);
202

203
204
205
206
207
208
209
              if (operatorID == SAMPLEGRID)
                {
                  sampleData(array1, gridSrcID, array2, gridIDsampled, resampleFactor);
                }
              else if (operatorID == SUBGRID)
                {
                  cropData(array1, gridSrcID, array2, gridIDsampled, subI0,subI1, subJ0, subJ1);
210
211
                }

212
              if ( nmiss )
213
                {
214
215
216
217
                  nmiss = 0;
                  double missval = vlistInqVarMissval(vlistID2, varID);
                  for ( int i = 0; i < gridsize2; i++ )
                    if ( DBL_IS_EQUAL(array2[i], missval) ) nmiss++;
218
219
                }

220
              streamWriteRecord(streamID2, array2, nmiss);
221
            }
222
          else
223
            {
224
              streamWriteRecord(streamID2, array1, nmiss);
225
226
            }
        }
227
228

      tsID++;
229
230
    }

231
232
  streamClose(streamID2);
  streamClose(streamID1);
233

234
  vlistDestroy(vlistID2);
235

236
237
238
  if ( vars ) Free(vars);
  if ( array2 ) Free(array2);
  if ( array1 ) Free(array1);
239

240
  if ( sbox ) Free(sbox);
241

242
  cdoFinish();
243

244
  return 0;
245
}